JaVa
   

XSLT

XML's power lies in its ability to represent data. However, to do something useful with the XML data, especially if it is document-centric XML, it would typically need to be translated into another format. The technology that enables this translation is the eXtensible Stylesheet Language (XSL). XSL is a language for expressing style sheets. A style sheet is an XML document that describes how to display an XML document of a particular type. XSL is a W3C specification and is broken down into three complementary technologies:

An XSLT processor, analogous to an XML parser, is an app that applies an XSL style sheet (which itself is an XML document and conforms to the XSL schema) to XML data input. Instead of modifying the original XML data, XSLT produces a result—typically HTML or XML and, in some rare cases, binary. Essentially, XSL uses XSLT to transform an XML source tree into an XML result tree, as Screenshot shows.

Java Click To expand
Screenshot: XSLT transformation process

These trees are logical structures that consists of nodes that may be produced by XML. They may be implemented as object models (e.g., DOM), a series of well-balanced parse events (e.g., callbacks received by the SAX ContentHandler), a series of requests (the result of which can describe a tree), or a stream of marked-up characters. Consider the example where you want to display part of the flutebank.com administrator information from the XML in Listing 9.1. Listing 9.5 shows the XSL a processor would take. Screenshot shows the resulting output from the transformation, as rendered in a browser.

Java ScreenShot
Screenshot: XML transformed into HTML Listing 9.5: The XSL style sheet used to transform the XML from Listing 9.1
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:n1="http://www.flutebank.com/schema" xmlns:contacts="http://www.flutebank.com/
schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <xsl:template match="/">
 <html>
 <body>
 <h4>Flutebank.com : Support personal contact information</h4>
 <table bgcolor="#AAB0AC" border="1" cellpadding="0" cellspacing="0"
 width="50%">
 <tr>
 <td>
 <h4>Name</h4>
 </td>
 <td>
 <xsl:for-each select="n1:flutebank">
 <xsl:for-each select="n1:administrator">
 <xsl:for-each select="n1:firstname">
 <xsl:apply-templates />
 </xsl:for-each>
 </xsl:for-each>
 </xsl:for-each> <xsl:for-each select="n1:flutebank">
 <xsl:for-each select="n1:administrator">
 <xsl:for-each select="n1:lastname">
 <xsl:apply-templates />
 </xsl:for-each>
 </xsl:for-each>
 </xsl:for-each>
 </td>
 </tr>
 <tr>
 <td>
 <h4>Phone:</h4>
 </td>
 <td>
 <xsl:for-each select="n1:flutebank">
 <xsl:for-each select="n1:administrator">
 <xsl:for-each select="n1:telephone">
 <xsl:for-each select="n1:desk">
 <xsl:apply-templates />
 </xsl:for-each>
 </xsl:for-each>
 </xsl:for-each>
 </xsl:for-each>
 </td>
 </tr>
 <<tr>
 <td>
 <h4>Email:</h4>
 </td>
 <td>
 <xsl:for-each select="n1:flutebank">
 <xsl:for-each select="n1:administrator">
 <xsl:for-each select="n1:email">
 <xsl:for-each select="n1:work">
 <xsl:apply-templates />
 </xsl:for-each>
 </xsl:for-each>
 </xsl:for-each>
 </xsl:for-each>
 </td>
 </tr>
 </table>
 </body>
 </html>
 </xsl:template>
 <xsl:template match="n1:administrator">
 <xsl:apply-templates />
 </xsl:template>
 <xsl:template match="n1:cellular">
 <xsl:apply-templates />
 </xsl:template>
</xsl:stylesheet>




Java End example

As with XML, this chapter is not intended to be a lesson on XSL or XPath syntax; numerous good sources are available for that. Vendor tools are also available, such as XMLSpy (www.xmlspy.com), that can generate XSL code based on the input XML and desired output, with minimal knowledge of these languages on the part of the user. So, why is XSLT important? A typical enterprise app that delivers content to users would use data from multiple EIS resources, apply some business rules and processing to the data, and serve the clients. As Screenshota shows, the clients could be other apps, users, or devices, all using the same logical data. To prevent rewriting the app and the presentation tier for every interface, an XSL-based processor that transcodes same document-centric XML into different formats (XML to WML, HTML, XML, XHTML, etc.) using XSL offers a cleaner content delivery mechanism but the same logical data set. The logical tiering for this approach is shown in Screenshotb.

Java Click To expand
Screenshota: Transcoding XML into different formats Java Click To expand
Screenshotb: Logical tiering

JAXP and XSLT

JAXP architecture accommodates XSLT by providing the same abstraction and pluggability as it does for SAX and DOM (see Screenshota).

Java Start Sidebar

JAXP endorses XLST 1.0 from the W3C at www.w3.org/TR/1999/REC-xslt-19991116.

Java End Sidebar

As Screenshot shows, JAXP is used to instantiate a TransformerFactory, which, in turn, is used to obtain a reference to a Transfomer specific to a style sheet. A Transformer takes a Source and transforms it into a Result. The source can be of any type: a DOMSource,a SAXSource (or the content parsed by a SAX parser), or a StreamSource.

Java Click To expand
Screenshot: JAXP and XSLT

The JAXP part that handles transformations is also known as the Transformation API for XML (TrAX) and is contained in the following packages:

To put the earlier mention about a source tree and a result tree into perspective, it is interesting to note that if the reference implementation, Xalan, is supplied with a DOMSource, it will use this as its internal tree representation. If the input is a SAXSource or StreamSource, it uses its own internal tree representation as the source tree, called an STree. This is more efficient than a general-purpose DOM, because it contains additional sorting optimizations. Tables 9.7 through 9.10 show the relevant interfaces in the above packages. The code to do the transformation would look something like the following:

 String xml = "saxexaple2.xml";
 String xsl = "fluteadmin.xsl";
// instantiate the factory
 TransformerFactory factory = TransformerFactory.newInstance();
// obtain a transformer from the factory for the XSL
 Transformer transformer = factory.newTransformer
 (new StreamSource(new File(xsl)));
// use the transformer to transform the source to a result
 transformer.transform(new StreamSource(new File(xml)),
 new StreamResult(System.out));


Another example would be to transform a DOM into another DOM in memory, using the XSL that is also in memory as a DOM (remember, an XSL document is also an XML document).

Table 9.7: The javax.xml.transform Package

Source

Defines the top level interface to wrap other specific sources.

Result

Defines the top level interface to wrap other specific results.

Templates

A template represents a set of XSL instructions in memory that need to be applied repeatedly to different XML data structures.

Transformer

The processor that applies the transformation.

TransformerFactory

A factory used to obtain a reference to the underlying Transformer.

URIResolver

Like schemas, a style sheet can have references to other style sheets, using an xsl:include or xsl:import statement. This is used to resolve such references and process them.

Table 9.8: The javax.xml.transform.dom Package

DOMSource

An interface to represent a DOM tree (an org.w3c.dom.Node) as the source of the XML data to be transformed

DOMResult

An interface to represent a DOM tree (an org.w3c.dom.Node) as the result of the transformation

 String xml = "saxexaple2.xml";
 String xsl = "fluteadmin.xsl";
// create a DOM from the XSL
 DocumentBuilderFactory domfactory = DocumentBuilderFactory.newInstance();
 domfactory.setNamespaceAware(true);
 DocumentBuilder parser = domfactory.newDocumentBuilder();
 Document xsldom = parser.parse(xsl);
// create a DOM from the source XML
 Document xmldom = parser.parse(xml);
// create the transfomer and transform the xml
 TransformerFactory factory = TransformerFactory.newInstance();
 Transformer transformer = factory.newTransformer(new DOMSource(xsldom));
 DOMResult result= new DOMResult();
 transformer.transform(new DOMSource(xmldom),result);



Table 9.9: The javax.xml.transform.sax Package

SAXSource

An interface to represent a SAX as the source of the XML data to be transformed. This wraps an org.xml.sax.InputSource and can futher be piped on a java.io.InputStream, java.io.Reader, or URI. (Typically, a string representing a java.net.URL.)

SAXResult

An interface to wrap a SAX ContentHandler invoked sequentially as a result of applying the transformation to the XML

TemplatesHander

A SAX ContentHandler that can be used to generate a Templates object from SAX source events

TransformerHandler

A SAX ContentHandler that can be used to generate a Result object from SAX source events

SAXTransformerFactory

A special kind of TransformerFactory that can be used to configure the SAX parser processing the XSL input

Table 9.10: The javax.xml.transform.stream Package

StreamSource

An interface to act as a pipe on different streams, as sources for the transformation (File, InputStream, Reader, or URL)

StreamResult

An interface to act as a pipe on different streams, as results for the transformation (File, OutputStream, Write, or URL)

Another example would be to use an empty transfomer not associated with a particular style sheet to transform the DOM—for example, from the code above into another form:

// As a convenience , print out the in memory DOM to
// the System.out using a null transform
 TransformerFactory factory = TransformerFactory.newInstance();
 Transformer nulltransformer = factory.newTransformer();
 nulltransformer.transform(new DOMSource(result.getNode()),
 new StreamResult(System.out));



Another example would be to use the transformer to obtain the associated style sheet from an XML document—for example, if the XML has a processing instruction such as:

<?xml-stylesheet type="text/xsl" href="fluteadmin.xsl"?>:
 String xml = "pitransform.xml";
 TransformerFactory factory = TransformerFactory.newInstance();
 Source xsl = factory.getAssociatedStylesheet (
 new StreamSource(xml),null, null, null);
 Transformer transformer = factory.newTransformer(xsl);
 transformer.transform(new StreamSource(xml),new StreamResult(System.out));


A common use for transformation involves applying the same style sheet to different or dynamically generated XML data, to produce dynamic output. For example, users request a service from a flutebank.com account service, resulting in the generation of user-specific stock portfolio XML data that needs to be transformed for rendering. In such scenarios, a Templates object should be used instead, to obtain the Transformer. A Templates object is immutable, thread safe, and guaranteed to work across multiple threads. Also, as we shall see with XSLTc, underlying implementations may provide further optimizations to deal with repeated transformations.

 String xml_1 = "pitransform.xml";
 String xml_2 = "saxexample2.xml";
 String xsl = "fluteadmin.xsl";
// instantiate the factory
 TransformerFactory factory = TransformerFactory.newInstance();
// obtain a template from the factory
 Templates template = factory.newTemplates(new StreamSource(xsl));
 Transformer transformer = template.newTransformer();
// use the transformer to transform the source to a result
 transformer.transform(new StreamSource(new File(xml_1)),
 new StreamResult(System.out));
 transformer.transform(new StreamSource(new File(xml_2)),
 new StreamResult(System.out));


JaVa
Comments