B.4 A More Advanced Example


Our final example triplet of source document, stylesheet, and result document involves converting an XML format into another XML format, rather than HTML. Example B-7 shows a simple XML document containing order information.

Example B-7. An XML document containing orders
<orders>   <order>     <item>Widget</item>     <price>50</price>     <quantity>3</quantity>   </order>   <order>     <item>Thingamajig</item>     <price>25</price>     <quantity>2</quantity>   </order>   <order>     <item>Whatchamacallit</item>     <price>35</price>     <quantity>1</quantity>   </order> </orders>

Example B-8 shows an XSLT stylesheet for converting this document into a summary format.

Example B-8. An XSLT stylesheet for processing orders
<xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">       <xsl:output indent="yes"/>       <xsl:template match="/">     <orderSummary>       <expensiveItems>         <xsl:apply-templates select="/orders/order[price >= 30]"/>       </expensiveItems>       <cheapItems>         <xsl:apply-templates select="/orders/order[price &lt; 30]"/>       </cheapItems>     </orderSummary>   </xsl:template>       <xsl:template match="order">     <xsl:element name="{item}">       <xsl:attribute name="totalPrice">         <xsl:value-of select="price * quantity"/>       </xsl:attribute>     </xsl:element>   </xsl:template>     </xsl:stylesheet>

This stylesheet introduces some more features of XPath and XSLT. Let's step through the stylesheet just as we did with the first two examples.

This time, the xsl:output method does not include a method attribute. Since it defaults to xml (as long as the result document's root element name is not html), the result will be serialized as a well-formed XML document. The indent attribute asks the processor, once again, to add line breaks and indentation to make the resulting document easy to read:

  <xsl:output indent="yes"/>

Inside the root template rule, we see some literal result elements. The orderSummary element will end up as the root, or document, element of the result document. And it will contain two child elements, expensiveItems and cheapItems:

  <xsl:template match="/">     <orderSummary>       <expensiveItems>         ...       </expensiveItems>       <cheapItems>         ...       </cheapItems>     </orderSummary>   </xsl:template>

Inside the expensiveItems element, we see the xsl:apply-templates instruction:

        <xsl:apply-templates select="/orders/order[price >= 30]"/>

The XPath expression /orders/order[price >= 30] selects all order element children of the root order element where the price child element's value is greater than or equal to 30. This test occurs inside square brackets and is called a predicate. (XPath predicates are similar to WHERE clauses in SQL.) Predicates are useful for filtering out all but the nodes you want from a given node-set. In this case, we only want to process certain orders where the price is greater than 30.

Inside the cheapItems element, we see a similar instruction:

        <xsl:apply-templates select="/orders/order[price &lt; 30]"/>

The XPath expression /orders/order[price &lt; 30] also contains a predicate. But in this case, the expression selects all the order elements that the first xsl:apply-templates instruction filtered out, namely the order elements where the price value is less than 30.

Certain markup characters in XML have special meaning and must be escaped when they occur inside element or attribute values. The XPath less-than operator (<), for example, must be escaped (as &lt;) when it occurs inside an attribute value (as in XSLT).


As we learned in the last section, the xsl:apply-templates instruction tells the XSLT processor to find matching template rules for each of the nodes in the node-set selected by the select attribute. Our stylesheet in Example B-8 includes only one other template rule:

  <xsl:template match="order">

This template rule happens to match all of the nodes selected by each of the two xsl:apply-templates instructions. In other words, all of the order elements being processed match the pattern order (in the match attribute).

Inside the template rule, we see a new XSLT instruction, xsl:element:

    <xsl:element name="{item}">       ...     </xsl:element>

The purpose of the xsl:element instruction is to create an element in the result document. In that respect, it is similar to a literal result element. However, unlike literal result elements, xsl:element instructions allow you to make the element name dynamic. In this case, the name of the element will be the value of the item child element of the current node (the item child of the order element being processed). The curly braces ({ }) are called an attribute value template and are replaced with the value returned by the XPath expression between them (item in this case). Without the curly braces, the XSLT processor would just create an item element (using the string item as the name of the new element, rather than evaluating item as an XPath expression).

Inside the xsl:element instruction, we see an xsl:attribute instruction:

      <xsl:attribute name="totalPrice">         ...       </xsl:attribute>

As you may have already guessed, the xsl:attribute element creates an attribute in the result. In this case, the name of the attribute will be totalPrice. The value of the totalPrice attribute is determined by the content of the xsl:attribute element. Looking inside the xsl:attribute element, we see an xsl:value-of instruction:

        <xsl:value-of select="price * quantity"/>

Unlike previous examples, the XPath expression shown here is an arithmetic expression, consisting of a location path multiplied by a location path. Actually, what happens is this: the location paths (price and quantity) are first evaluated and converted to numbers. Then those numbers are multiplied by each other. Thus, the value of the totalPrice attribute in the result will be the product of the values of the price and quantity child elements of the order element currently being processed.

Finally, Example B-9 shows the result of applying the XSLT stylesheet (Example B-8) against the source document (Example B-7).

Example B-9. The result of applying the stylesheet in Example B-8 against the XML document in Example B-7
<?xml version="1.0"?> <orderSummary>   <expensiveItems>     <Widget totalPrice="150"/>     <Whatchamacallit totalPrice="35"/>   </expensiveItems>   <cheapItems>     <Thingamajig totalPrice="50"/>   </cheapItems> </orderSummary>

As you can see, there is an element to correspond to each of the original order elements from Example B-7. The name of each element varies according to the value of the original item child element (Widget, Whatchamacallit, or Thingamajig). They are divided up into "expensive" and "cheap" items depending on their original price values. For example, since the "Thingamajig" item's price was only 25 (which is less than 30), it ended up inside the cheapItems element. Finally, the totalPrice attribute in each case consists of the original price value multiplied times the original quantity value.



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