7.5 Using Result Tree Fragments

As you saw earlier, a variable value, created with a template as element content, creates a result tree fragment. The stylesheet in Example 7-2, fragment.xsl, constructs a variable value for discount using a template with a variable element, and then later accesses that value with copy-of.

Example 7-2. Copying a variable
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:output doctype-system="catalog.dtd"/> <xsl:variable name="discount"> <discount>0.40</discount> <discountPrice><xsl:value-of select="format-number(catalog/item/price *  0.60, '###.00')"/></discountPrice> </xsl:variable> <xsl:template match="catalog">  <xsl:copy>   <xsl:apply-templates select="item"/>  </xsl:copy> </xsl:template>     <xsl:template match="item">  <xsl:copy>   <xsl:copy-of select="@id"/>   <xsl:copy-of select="maker|description|size|price"/>   <xsl:copy-of select="$discount"/>   <xsl:copy-of select="currency"/>  </xsl:copy> </xsl:template>     </xsl:stylesheet>

Notice the value-of contained in discountPrice in variable. The first argument of format-number( ) uses a location path to address the content of the price element in the source tree. The context node for evaluating a global variable is the root node of the original source document; that's why the location path uses catalog/item/price instead of /catalog/item/price, an absolute location path.

Later, in the template for item, copy-of elements copy the id attribute from the source item and the nodes contained in discount's result tree fragment.

To test it out, enter this command line:

saxon price.xml fragment.xsl

You will get this outcome:

<?xml version="1.0" encoding="utf-8"?>     <!DOCTYPE catalog   SYSTEM "catalog.dtd"> <catalog>    <item >       <maker>Scratchmore</maker>       <description>Wool sweater</description>       <size>L</size>       <price>120.00</price>       <discount>0.40</discount>       <discountPrice>72.00</discountPrice>       <currency>USD</currency>    </item> </catalog>

A result tree fragment does not have to be well-formed XML. For example, you could also just use a bit of text in a result tree fragment, as shown in the variable definition for discount in Example 7-3, frag.xsl.

Example 7-3. Using text as a result tree fragment
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:output doctype-system="catalog.dtd"/> <xsl:variable name="discount">0.70</xsl:variable> <xsl:variable name="discountPrice" select="format-number(catalog/item/price -  (catalog/item/price) * $discount, '###.00')"/>     <xsl:template match="catalog">  <xsl:copy>   <xsl:apply-templates select="item"/>  </xsl:copy> </xsl:template>     <xsl:template match="item">  <xsl:copy>   <xsl:copy-of select="@id"/>   <xsl:copy-of select="maker|description|size|price"/>   <discount><xsl:value-of select="$discount"/></discount>   <discountPrice><xsl:value-of select="$discountPrice"/></discountPrice>   <xsl:copy-of select="currency"/>  </xsl:copy> </xsl:template>     </xsl:stylesheet>

The variable discount contains only the text 0.70. (It's not best to define a simple value like 0.70 as a tree fragment, as it is somewhat more costly processing-wise to do so.) When the discountPrice variable is defined, it contains a reference to discount as part of its definition. The two variables are referenced later in the stylesheet by instances of value-of.

You can reference a global variable before you define it, but you must define a local variable before you reference it.


Watch what happens with this command:

xalan -i 1 price.xml frag.xsl

Here is the result:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE catalog SYSTEM "catalog.dtd"> <catalog>  <item >   <maker>Scratchmore</maker>   <description>Wool sweater</description>   <size>L</size>   <price>120.00</price>   <discount>0.70</discount>   <discountPrice>36.00</discountPrice>   <currency>USD</currency>  </item> </catalog>

Before concluding, I should mention a few more things about result tree fragments. Only XSLT 1.0 allows you to copy result tree fragments or use them as strings. However, the node-set( ) extension function offered by many XSLT 1.0 processors allows you to use a result tree fragment as a tree of temporary nodes. node-set( ) is not actually part of XSLT 1.0, but it is a useful extension added by many XSLT processors. You will learn how to use two versions of node-set( ) in Chapter 15. XSLT 2.0 uses temporary trees rather than result tree fragments, which are stricter. Unlike its 1.0 predecessor, XSLT 2.0 is a tree of XML nodes and cannot contain mere fragments of text.



Learning XSLT
Learning XSLT
ISBN: 0596003277
EAN: 2147483647
Year: 2003
Pages: 164

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