Sun Microsystems's Java API for XML (JAXP) version 1.1 expands the capabilities of the Java XML parsing engine. This new version includes solid support for XML Stylesheet Language Translation (XSLT), an XML specification that allows you to translate XML documents between differing formats. In this article, we'll walk you through the process of setting up an XML Style Language (XSL) document and translating a document from one format to another using the XSL document.
What is XSL/XSLT?
The XSL and XSLT specifications are designed to help systems understand disparate XML document types. Because the different systems have different requirements and because there is generally not a single generic document type, there is the need to translate XML documents from one type to another. The XML Stylesheet Language (XSL) is an XML specification that describes how to translate from one document type to another (or more generally, from one XML format to any other format that can be described in the XSL template). The XML Stylesheet Language Translation (XSLT) is the process that interprets the data in an XML document and merges it with the layout of the stylesheet template. The result is a new documentand usually a new XML document.
The XSL document
XSL provides a language for specifying how to lay out the data in an XML document. Let's take a simple XML document for example, as shown in Listing 1.
Listing 1: simple.xml
<SimpleCustomer>
<FirstName>John</FirstName>
<MiddleInitial/>
<LastName>Doe</LastName>
<Address>1234 Michigan Ave</Address>
<City>Chicago</City>
<State>IL</State>
<Zip>60614</Zip>
<Phone>312-555-1212</Phone>
Email>[email protected]</Email>
</SimpleCustomer>
Now suppose we want to take this data and format it for an outgoing letter. We want the resulting data to appear like this:
<RecipientAddress>
<Line1>John Doe</Line1>
<Line2>1234 Michigan Ave</Line2>
<Line3>Chicago, IL 60614</Line3>
</RecipientAddress>
We'll start by creating an XSL template that specifies how to translate our <SimpleCustomer> into a <RecipientAddress>. Listing 2 shows our simple.xsl template.
Listing 2: simple.xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="SimpleCustomer">
<RecipientAddress>
<Line1><xsl:value-of select="FirstName"/><xsl:text>
</xsl:text><xsl:value-of select="MiddleInitial"/><xsl:text>
</xsl:text><xsl:value-of select="LastName"/></Line1>
<Line2><xsl:value-of select="Address"/></Line2>
<Line3><xsl:value-of select="City"/>,<xsl:text>
</xsl:text><xsl:value-of select="State"/><xsl:text>
</xsl:text><xsl:value-of select="Zip"/></Line3>
</RecipientAddress>
</xsl:template>
</xsl:stylesheet>
As you can see, the XSL template is really just another XML document. The important tags are <xsl:template> and <xsl:value-of>. These tell the XSLT engine how to find pieces of data within the XML document. In this case, the <xsl:template> tag is configured to look for a tag that matches "SimpleCustomer". When the SimpleCustomer tag is found, it outputs the "normal" looking XML tags that follow (such as <RecipientAddress> and <Line1>). When the engine gets to the <xsl:value-of> tag, it looks for an element inside of <SimpleCustomer> called <FirstName> and outputs the content of that element. The <xsl:text> </xsl:text> construct is necessary in order to keep the resulting name from being run together (i.e., JohnDoe).
Programmatically transforming XML
Now that we have the building blocks for our transformation, let's examine how to programmatically format our simple.xml document using the simple.xsl template. The process includes retrieving a Transformer instance from the TransformerFactory, and applying the transformation to an XML document. Listing 3 shows the simple.java file used to implement the translation.
Listing 3: simple.java
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import java.io.*;
public class simple {
public static void main(String[] argv) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer(new StreamSource(argv[0]));
t.transform(new StreamSource(argv[1]), new StreamResult(baos));
System.out.println(baos.toString());
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
}
}
The simple class creates a new TransformerFactory() using the static method newInstance(). The factory is used to generate a new Transformer based on the file identified in the first command line argument (simple.xsl). The Transformer's transform() method is called, passing in the XML document, from the second command line argument (simple.xml), and an output stream (in this case a ByteArrayOutputStream). When transform() is called, the XML document is transformed using the XSL stylesheet, and the result is delivered to the output stream. This class can be called using the following command line (assuming simple.class is in your CLASSPATH and simple.xsl and simple.xml are in your current directory):
java simple simple.xsl simple.xml
Summary
XSL Transformations allow you to reinterpret the data in XML documents and deliver them in new formats. In this article, we've shown how to create a basic XSL template to format an XML document. We've also illustrated the basic process for implementing an XSL transformation programmatically using the JAXP 1.1 parser.