Previous | Next
Transformation ProcessNow that we have seen an example, let's back up and talk about some basics. In particular, it is important to understand the relationship between
XML Tree Data Structure Every well-formed XML document forms a tree data structure. The document itself is always the root of the tree, and every element within the document has exactly one parent. Since the document itself is the root, it has no parent. As you learn XSLT, it can be helpful to draw pictures of your XML data that show its tree structure. Figure 2-2 illustrates the tree structure for discussionForumHome.xml. Figure 2-2. Tree structure for discussionForumHome.xmlThe document itself is the root of the tree and may contain processing instructions, the document root element, and even comments. XSLT has the ability to select any of these items, although you will probably want to select elements and attributes when transforming to HTML. As mentioned earlier, the A tree data structure is fundamentally recursive because it consists of leaf nodes and smaller trees. Each of these smaller trees, in turn, also consist of leaf nodes and still smaller trees. Algorithms that deal with tree structures can almost always be expressed recursively, and XSLT is no exception. The processing model adopted by XSLT is explicitly designed to take advantage of the recursive nature of every well-formed XML document. This means that most stylesheets can be broken down into highly modular, easily understandable pieces, each of which processes a subset of the overall tree (i.e., a subtree). Two important concepts in XSLT are the current node and current node list. The current node is comparable to the current working directory on a file system. The Recursive Processing with TemplatesMost transformation in XSLT is driven by two elements:
As the XSLT transformation process continues, the current node and current node list are constantly changing. This is a good thing, since you do not want to constantly search for patterns beginning from the document root element. You are not limited to traversing down the tree, however; you can iterate over portions of the XML data many times or navigate back up through the document tree structure. This gives XSLT a huge advantage over CSS because CSS is limited to displaying the XML in the order in which it appears in the document. Let's suppose that your source document contains the following XML: <school> <name>SIUC</name> <city>Carbondale</city> <state>Illinois</state> </school> The following template could be used to match the <xsl:template match="school"> <b><xsl:value-of select="name"/> is located in <xsl:value-of select="city"/>, <xsl:value-of select="state"/>.</b> </xsl:template> The result will be something like: <b>SIUC is located in Carbondale, Illinois.</b> As you can see, elements that do not start with
<xsl:text> is located in </xsl:text>. This provides explicit control over how whitespace and linefeeds are treated.
Built-in Template RulesAll XSLT processors must include four built-in template rules that have lower precedence than any other rules, so they can be overridden by simply writing a new template rule that matches the same pattern. The best way to think about built-in rules is to assume they are always in the background, ready to be applied if no other rule is found that matches a node. The first rule allows recursive processing to continue in case an explicit rule does not match the current node or the root node: <xsl:template match="*|/"> <xsl:apply-templates/> </xsl:template> This template matches all elements (*) and the root node (/), i.e., the document itself. It will not match processing instructions, comments, attributes, or text. The The second built-in rule is identical to the first, except it applies to each mode used in the stylesheet: <xsl:template match="*|/" mode="m"> <xsl:apply-templates mode="m"/> </xsl:template> Template modes are discussed in the next chapter, so we will not go into details here. The third built-in rule simply copies all text and attribute nodes to the result tree: <xsl:template match="text( )|@*"> <xsl:value-of select="."/> </xsl:template> And finally, the built-in rule for processing instructions and comments does nothing. This is why comments and processing instructions in the input XML data do not automatically show up in the result tree: <xsl:template match="processing-instruction()|comment( )"/> A Skeleton StylesheetAs your XML documents get more complex, you will most likely want to break up your stylesheets into several templates. The starting point is a template that matches the <xsl:template match="/"> ...content </xsl:template> This template matches the document itself and is usually where you output the basic It should be stressed that this is not the only way to write a stylesheet, but it is a very natural way to handle the recursive nature of XML. Example 2-4 contains a skeleton XSLT stylesheet that you can use as a starting point for most of your projects. Example 2-4. Skeleton stylesheet<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html"/> <!--**************************************************************** ** "/" template matches the document and is the starting point *************************************************************--> <xsl:template match="/"> <html> <head> <title>[title goes here]</title> </head> <body> <xsl:apply-templates select="[some XPath expression]"/> </body> </html> </xsl:template> <!--**************************************************************** ** "[???]" template *************************************************************--> <xsl:template match="???"> [continue the process...] <xsl:apply-templates select="[another XPath expression]"/> [you can also include more content here...or even include multiple apply-templates...] </xsl:template> </xsl:stylesheet> Deciding how to modularize the stylesheet is a subjective process. One suggestion is to look for moderately sized chunks of XML data repeated numerous times throughout a document. For example, a When you need to produce HTML tables or unordered lists in the result tree, two templates (instead of one) can make the job very easy. The first template will produce the <!-- the outer template produces the unordered list --> <!-- (note: plural 'customers') --> <xsl:template match="customers"> |