O'Reilly Book Excerpts: Learning Java, 2nd Edition
XML Basics for Java Developers, Part 5by Patrick Niemeyer and Jonathan Knudsen
In this final in a series of XML basics for Java developers book excerpts from Learning Java, 2nd Edition, get an introduction to XSL/XSLT and Web services.
Earlier in this chapter, we used a
Transformer object to copy a DOM representation of an example back to XML text. We mentioned then that we were not really tapping the potential of the
Transformer. Now we'll give you the full story.
javax.xml.transform package is the API for using the XSL/XSLT transformation language. XSL stands for Extensible Stylesheet Language. Like Cascading Stylesheets for HTML, XSL allows us to "mark up" XML documents by adding tags that provide presentation information. XSL Transformation (XSLT) takes this further by adding the ability to completely restructure the XML and produce arbitrary output. XSL and XSLT together comprise their own programming language for processing an XML document as input and producing another (usually XML) document as output. (From here on in we'll refer to them collectively as XSL.)
XSL is extremely powerful, and new applications for its use arise every day. For example, consider a web portal that is frequently updated and which must provide access to a variety of mobile devices, from PDAs to cell phones to traditional browsers. Rather than recreating the site for these and additional platforms, XSL can transform the content to an appropriate format for each platform. Multilingual sites also benefit from XSL.
You can probably guess the caveat that we're going to issue next: XSL is a big topic worthy of its own books (see, for example, O'Reilly's Java and XSLT by Eric Burke, a fellow St. Louis author), and we can only give you a taste of it here. Furthermore, some people find XSL difficult to understand at first glance because it requires thinking in terms of recursively processing document tags. Don't be put off if you have trouble following this example; just file it away and return to it when you need it. At some point, you will be interested in the power transformation can offer you.
XSL is an XML-based standard, so it should come as no surprise that the language is based on XML. An XSL stylesheet is an XML document using special tags defined by the XSL namespace to describe the transformation. The most basic XSL operations include matching parts of the input XML document and generating output based on their contents. One or more XSL templates live within the stylesheet and are called in response to tags appearing in the input. XSL is often used in a purely input-driven way, where input XML tags trigger output in the order that they appear, using only the information they contain. But more generally, the output can be constructed from arbitrary parts of the input, drawing from it like a database, composing elements and attributes. The XSLT transformation part of XSL adds things like conditionals and for loops to this mix, enabling arbitrary output to be generated based on the input.
An XSL stylesheet contains as its root element a stylesheet tag. By convention, the stylesheet defines a namespace prefix
xsl for the XSL namespace. Within the stylesheet are one or more template tags containing a
match attribute describing the element upon which they operate.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> I found the root of the document! </xsl:template> </xsl:stylesheet>
When a template matches an element, it has an opportunity to handle all the children of the element. The simple stylesheet above has one template that matches the root of the input document and simply outputs some plain text. By default, input not matched is simply copied to the output with its tags stripped (HTML convention). But here we match the root so we consume the entire input.
In This Series
match attribute can refer to elements in a hierarchical path fashion starting with the root. For example,
match="/Inventory/Animal" would match only the
Animal elements from our zooinventory.xml file. The path may be absolute (starting with "/") or relative, in which case the template detects whenever that element appears in any context. The
match attribute actually uses an expression format called XPath that allows you to describe element names using a syntax somewhat similar to a regular expression. XPath is a powerful syntax for describing sets of nodes in XML, and it includes notation for describing sets of child nodes based on path and even attributes.
Within the template, we can put whatever we want, as long as it is well-formed XML (if not, we can use a CDATA section). But the real power comes when we use parts of the input to generate output.
value-of tag is used to output the content of an element or a child of the element. For example, the following template would match an
Animal element and output the value of its
<xsl:template match="Animal"> Name: <xsl:value-of select="Name"/> </xsl:template>
select attribute uses a similar expression format to match. Here we tell it to print the value of the
Name element within
Animal. We could have used a relative path to a more deeply nested element within
Animal or even an absolute path to another part of the document. To refer to its own element, we can simply use "." as the path. The
select expression can also retrieve attributes from the elements it refers to.
Now if we try to add the
Animal template to our simple example, it won't generate any output. What's the problem? Well, if you recall, we said that a template matching an element has the opportunity to process all its children. We already have a template matching the root ("/"), so it is consuming all the input. The answer to our dilemma--and this is where things get a little tricky--is to delegate the matching to other templates using the
apply-templates tag. The following example correctly prints the names of all the animals in our document:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> Found the root! <xsl:apply-templates/> </xsl:template> <xsl:template match="Animal"> Name: <xsl:value-of select="Name"/> </xsl:template> </xsl:stylesheet>
Note that we still have the opportunity to add output before and after the
apply-templates tag. But upon invoking it, the template matching continues from the current node. Next we'll use what we have so far and add a few bells and whistles.
Pages: 1, 2