B.3 A Rule-Based Stylesheet


All XSLT processing is rule-based, it's just that some stylesheets take advantage of this fact more than others. Our first stylesheet (Example B-2) only used one template rule (where match="/"). Now we'll look at a stylesheet that uses multiple template rules.

Example B-4 shows the source document for this example transformation. It is a simple article that contains a heading and multiple paragraphs. Inside the paragraphs, there is some "mixed content," i.e., elements that contain both text and elements (e.g., the emphasis element).

Example B-4. A simple XML document containing marked-up text
<article>   <heading>This is a short article</heading>   <para>This is the <emphasis>first</emphasis> paragraph.</para>   <para>This is the <strong>second</strong> paragraph.</para> </article>

Example B-5 shows a simple XSLT stylesheet that is designed to process documents that look like the XML document in Example B-4.

Example B-5. An XSLT stylesheet with multiple template rules
<xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">       <xsl:output method="xml" indent="yes"/>       <xsl:template match="/">     <html>       <head>         <title>           <xsl:value-of select="/article/heading"/>         </title>       </head>       <body>         <h1>           <xsl:value-of select="/article/heading"/>         </h1>         <xsl:apply-templates select="/article/para"/>       </body>     </html>   </xsl:template>       <xsl:template match="para">     <p>       <xsl:apply-templates/>     </p>   </xsl:template>       <xsl:template match="emphasis">     <i>       <xsl:apply-templates/>     </i>   </xsl:template>       <xsl:template match="strong">     <b>       <xsl:apply-templates/>     </b>   </xsl:template>     </xsl:stylesheet>

This stylesheet contains an xsl:output element too:

  <xsl:output method="xml" indent="yes"/>

In this case the result document will be serialized in XML format, so that the result will be well-formed XML (all elements will have end tags, etc.).

The root template rule is very similar to the stylesheet we saw in Example B-2, except that here the values of the title and h1 elements are dynamic:

  <xsl:template match="/">     <html>       <head>         <title>           <xsl:value-of select="/article/heading"/>         </title>       </head>       <body>         <h1>           <xsl:value-of select="/article/heading"/>         </h1>

The xsl:value-of instructions see to it that both the title and h1 elements in the result will have the same value as the heading element in the source document (Example B-4).

This snippet demonstrates how you can re-use the same text in the source document in multiple places in the result. The string This is a short article will appear both as the resulting HTML document's title and as its top-level heading.

In fact, you can use as little or as much of the source tree as you want when creating a result tree. XSLT leaves it up to you. You could copy the source tree verbatim into the result tree (called an "identity transformation"), or you could create an entirely unrelated result tree, ignoring what's in the source tree. The most useful stylesheets are usually those that do something in between these two extremes.


So far, there is not much difference between this example and the first stylesheet we looked at (Example B-2). The root template rule contains a basic template of the result document, along with some placeholders for dynamic content (xsl:value-of instructions). What distinguishes this stylesheet from the first one is the use of the next XSLT instruction that we see, the xsl:apply-templates instruction:

  <xsl:apply-templates select="/article/para"/>

The purpose of this instruction is to tell the XSLT processor to find a matching template rule for each of the nodes returned by the XPath expression in the instruction's select attribute. In this case, the XPath expression /article/para returns a node-set consisting of two elements. Looking back at the source document (Example B-4), we see that the article root element contains two para elements. For each of these element nodes, the XSLT processor tries to find a matching template rule.

The xsl:apply-templates instruction is similar to the xsl:for-each instruction, in that both instructions iterate over a set of nodes that is selected using the instruction's select attribute. The difference between them is what happens to each node. The content of the xsl:for-each element statically dictates what content to insert into the result tree; the same thing happens for each node in the node-set. On the other hand, the xsl:apply-templates instruction dynamically decides what to do with each node in the node-set. It acts like a big, invisible if/else statement, determining which template rule to apply based on which node is currently being processed. Unlike the xsl:for-each instruction, it has the potential of doing something different for every node that it processes.

In this case, it first looks for a template rule for the first para element. After it has found a matching template rule and has finished applying it, it then looks for a template rule for the second para element. If there were more than two para elements in the source document, then it would continue to do this until it has finished finding and applying a template rule for each of the nodes in the node-set.

Where does the XSLT processor find these template rules? Well, the first place it looks is inside your stylesheet. We've already seen that a template rule is any xsl:template element that has a match attribute, which means that our stylesheet contains four template rules. (Their order doesn't matter.) In this case, since we're processing para elements, the second template rule in the stylesheet matches, as determined by the value of its match attribute:

  <xsl:template match="para">

The value of the match attribute is called a pattern. In this case the pattern para successfully matches the para elements that are being processed via xsl:apply-templates.

Inside this template rule, there is a p literal result element. Effectively, there will be one p element in the result tree for each para element in the source tree:

    <p>       <xsl:apply-templates/>     </p>

The xsl:apply-templates instruction inside the p element has no select attribute. When the select attribute is absent, the instruction is equivalent to <xsl:apply-templates select="child::node( )"/>. This means "Process all child nodes, regardless of their type." In this case, the current node being processed is a para element. The para elements in our source document contain both elements and text, so the node-set to process will consist of both elements and text nodes. Since our stylesheet does not explicitly define a template rule for text nodes, then one of XSLT's built-in template rules is applied. The built-in rule for text nodes is to copy the node to the result tree. Thus, the p elements in the result tree will effectively contain the same text as their corresponding para elements in the source tree.

Our stylesheet contains two other template rules, one for emphasis elements and one for strong elements:

  <xsl:template match="emphasis">     <i>       <xsl:apply-templates/>     </i>   </xsl:template>       <xsl:template match="strong">     <b>       <xsl:apply-templates/>     </b>   </xsl:template>

The effect of these rules is that emphasis elements in the source document get transformed into i elements in the result document, and strong elements in the source document get transformed into b elements in the result document.

Finally, we see the result of applying the stylesheet (Example B-5) to our simple XML source document (Example B-4). Example B-6 shows the XML serialization of the result tree of this transformation.

Example B-6. The resulting XML document
<?xml version="1.0" encoding="utf-8"?> <html>   <head>     <title>This is a short article</title>   </head>   <body>     <h1>This is a short article</h1>     <p>This is the <i>first</i> paragraph.</p>     <p>This is the <b>second</b> paragraph.</p>   </body> </html>

As you can see, the title and h1 elements have the same value (from the source document's heading element). Also, the para elements have been converted to p elements, the emphasis element has been converted to an i element, and the strong element has been converted to a b element.



Office 2003 XML
Office 2003 XML
ISBN: 0596005385
EAN: 2147483647
Year: 2003
Pages: 135

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net