Xslt Processing with Java

Transform XML using XSLT in JAVA

If you want to use StreamSource(String systemId) then a valid local absolute file URI would look something like: new StreamSource("file:///C:/test2/xsltFilePersonnes.xsl").

But I think running your Java code in a certain folder (e.g. C:\test2) and then using relative URIs like new StreamSource("xsltFilePersonnes.xsl") should work as well.

Saxonica also has JAXP samples for 9.8 online here.

How to pass a XML document to XSL file using Javax.xml.transformer API?

I think your issue is in the XSLT. Change

<xsl:variable name="lookup" select="('documentFile')/>  . 

to

<xsl:variable name="lookup" select="document('lookup')/>

this will cause the transformer to make the DOM of your document accessible in the variable lookup. The key lookup comes from docs.put("lookup", documentFile);

Dynamically Pass Multiple XML Sources to XSL Transformation via URIResolver.

Full Working Example:

Be there three XML files: repo.xml, books.xml and articles.xml. The repo.xml contains status information about books and articles. The files articles.xml and books.xml contain title information about each item. The goal is to print status information of all books and articles together with the title information. The entries in all files are connected via id keys.

Find complete example at github or copy/paste the listings below.

repo.xml

<repository>
<book>
<id>1</id>
<status>available</status>
</book>
<book>
<id>2</id>
<status>lost</status>
</book>
<article>
<id>1</id>
<status>in transit</status>
</article>
</repository>

books.xml

<books>
<book id="1">
<title>Book One</title>
</book>
<book id="2">
<title>Book Two</title>
</book>
<book id="3">
<title>Book Three</title>
</book>
</books>

articles.xml

<articles>
<article id="1">
<title>Article One</title>
</article>
<article id="2">
<title>Article Two</title>
</article>
<article id="3">
<title>Article Three</title>
</article>
</articles>

join.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" encoding="UTF-8" indent="yes" />

<xsl:template match="/">
<titleStatusJoin>
<xsl:for-each select="//book">
<xsl:variable name="myId" select="id" />
<book>
<status>
<xsl:value-of select="status" />
</status>
<title>
<xsl:for-each select="document('bookFile')//book">
<xsl:variable name="bookId" select="@id" />
<xsl:choose>
<xsl:when test="$myId = $bookId">
<xsl:value-of select="title" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
</title>
</book>
</xsl:for-each>
<xsl:for-each select="//article">
<xsl:variable name="myId" select="id" />
<article>
<status>
<xsl:value-of select="status" />
</status>
<title>
<xsl:for-each select="document('articleFile')//article">
<xsl:variable name="bookId" select="@id" />
<xsl:choose>
<xsl:when test="$myId = $bookId">
<xsl:value-of select="title" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
</title>
</article>
</xsl:for-each>

</titleStatusJoin>
</xsl:template>
</xsl:stylesheet>

Use this Java code...

@Test
public void useMultipleXmlSourcesInOneXsl3() {
InputStream xml = Thread.currentThread().getContextClassLoader().getResourceAsStream("stack54335576/repo.xml");
InputStream xsl = Thread.currentThread().getContextClassLoader().getResourceAsStream("stack54335576/join3.xsl");
InputStream booksXml = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("stack54335576/books.xml");
InputStream articlesXml = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("stack54335576/articles.xml");
Document booksDom = readXml(booksXml);
Document articlesDom = readXml(articlesXml);
Map<String, Document> parameters = new HashMap<>();
parameters.put("bookFile", booksDom);
parameters.put("articleFile", articlesDom);
xslt(xml, xsl, parameters);
}

public final void xslt(InputStream xml, InputStream xsl, Map<String, Document> parameters) {
try {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(xsl));
transformer.setURIResolver((href, base) -> new DOMSource(parameters.get(href)));
transformer.transform(new StreamSource(xml), new StreamResult(System.out));
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private Document readXml(InputStream xmlin) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
return db.parse(xmlin);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

...to produce this output

<?xml version="1.0" encoding="UTF-8"?>
<titleStatusJoin>
<book>
<status>available</status>
<title>Book One</title>
</book>
<book>
<status>lost</status>
<title>Book Two</title>
</book>
<article>
<status>in transit</status>
<title>Article One</title>
</article>
</titleStatusJoin>

different results of xsl transformation using java transformer and command line processor

Make sure you explicitly use a namespace aware DocumentBuilderFactory if you want to process XML and XSLT with Java as otherwise you won't get a meaningful result, XSLT itself is XML depending on namespaces and any XML input it uses is also better processed with namespace support.

Of course to simply use XML from a file as the input you don't need a DocumentBuilder and a DOMSource, you can use a StreamSource as well where then the XSLT processor takes care of processing the input in a namespace aware mode.

How to transform each xml node with Saxon XSLT?

The XSLT template can be modified as below. The elements can be selected according to the required sequence.

<xsl:template match="employee">
<xsl:value-of select="ancestor::employees/@stage, details/name, details/age, address/street, address/nr" separator=", " />
<xsl:text> </xsl:text>
</xsl:template>

After replacing the ... with some dummy values in the <address> element the following output is generated using the above template.

test, Joe, 34, test, 12
test, Sam, 24, test1, 123

For transforming the XML (using XSLT) in Java, I use the following code snippet most of the time. This method returns the transformed XML as a String. The required library is saxon9he.jar. You may have to upgrade the library version for using with XSLT 3.0

public static String transformXML(String xml, InputStream xslFile) {
String outputXML = null;
try {
System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(xslFile));
Source xmlStream = new StreamSource(new StringReader(xml));
StringWriter writer = new StringWriter();
Result result = new StreamResult(writer);
transformer.transform(xmlStream, result);
outputXML = writer.getBuffer().toString();
} catch (TransformerConfigurationException tce) {
tce.printStackTrace();
} catch (TransformerException te) {
te.printStackTrace();
}
return outputXML;
}

How to run saxon xslt transformation in java

The documentation is here: http://www.saxonica.com/documentation/index.html#!using-xsl/embedding

Saxon offers two APIs for running XSLT transformations from a Java application: the JAXP API, and the s9api API. JAXP is a standard interface offered by almost all Java XSLT processors, so you want to use this one if you want your application to be portable; its disadvantage is that (a) it's very oriented to XSLT 1.0 and that makes it hard to take advantage of new capabilities in XSLT 2.0 and XSLT 3.0, and (b) it doesn't integrate especially well with APIs for related tasks such as schema processing and XPath evaluation.

The s9api API is much more closely matched to Saxon's capabilities across a variety of tasks including XSLT, XQuery, XPath, and XSD validation, but isn't portable.

It's your choice.



Related Topics



Leave a reply



Submit