7.2 Using Variables

Variables in XSLT allow you to associate a name with a value, making it easier to use a given value more than once. I'll start the series of examples in this chapter with a single, global variable that contains a numeric value that is available in every template in the stylesheet, if needed. The following document, price.xml, in examples/ch07, represents a single catalog entry:

<?xml version="1.0"?> <!DOCTYPE catalog SYSTEM "price.dtd">     <catalog>  <item >   <maker>Scratchmore</maker>   <description>Wool sweater</description>   <size>L</size>   <price>120.00</price>   <currency>USD</currency>  </item> </catalog>

price.xml happens to be valid with regard to the DTD price.dtd, also in examples/ch07. The stylesheet variable.xsl derives a discounted price from price.xml and outputs new content for the catalog:

<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" select="0.10"/>     <xsl:template match="catalog">  <xsl:copy>   <xsl:apply-templates select="item"/>  </xsl:copy> </xsl:template>     <xsl:template match="item">  <xsl:copy>   <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>   <xsl:copy-of select="maker|description|size|price"/>   <discount><xsl:value-of select="$discount"/></discount>   <discountPrice><xsl:value-of select="price - (price * $discount)"/></discountPrice>   <xsl:copy-of select="currency"/>  </xsl:copy> </xsl:template>     </xsl:stylesheet>

The stylesheet outputs XML that includes a new document type declaration referencing catalog.dtd (available in examples/ch07). Because the variable element is at the top level, it declares a global variable, discount, that is available or visible to all templates in the stylesheet. This variable is referenced later in the stylesheet with the variable reference $discount. A variable reference is preceded by a dollar sign ($).

There is no internal conflict, by the way, between the element name discount and the variable name discount. There is also no name conflict between a variable defined on the top level and one with the same name defined in a template. However, there will be a name conflict if two or more variables share the same name and are defined on the top level (unless they have a different import precedence; see Chapter 13 for an explanation), or if they share the same name and are defined locally in a template.


The stylesheet makes copies of the maker, description, size, and price elements (maker|description|size|price). In Chapter 4, the | operator was said to imply or. In this instance, the | operator implies and. In other words, the elements maker and description and size and price are all copied. (| can generally be read as union.)

The stylesheet creates two new elements in the result tree, discount and discountPrice. The content of these elements is formed with the aid of the discount variable, which contains a discount percentage of 10 percent (0.10). The discount and discountPrice elements will contain content that is computed with the value of the discount variable.

To see the result, transform price.xml with variable.xsl with the following command:

xalan -v -i 1 price.xml variable.xsl

The -v option instructs Xalan to validate the source document price.xml against the DTD it references in its document type declaration (price.dtd), not the DTD output document references (catalog.dtd). The -i option indicates that child elements should be indented by one space per child. This command will give you the following output:

<?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.1</discount>   <discountPrice>108</discountPrice>   <currency>USD</currency>  </item> </catalog>

The added discount element reports the discount percentage, and the new discountPrice element contains the calculated discounted price. You can improve the appearance of numbers in the discount and discountPrice elements by using the format-number( ) function in the stylesheet. (format-number( ) was mentioned in Chapter 5 and you will learn more about it in Chapter 9.) variable-alt.xsl uses both the format-number( ) and document( ) functions:

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

Xalan reports that it does not support the format-number( ) function, so I'll use the Instant Saxon processor for this example instead. Instant Saxon 6.5.3, the last version of Instant Saxon, runs on the Windows platform and is available for download from http://saxon.sourceforge.net. (Or just use saxon.exe in examples/ch07). After Instant Saxon is installed, apply variable-alt.xsl to price.xml with this line:

saxon price.xml variable-alt.xsl

You will see a difference from the output of variable.xsl with that of the output of variable-alt.xsl:

<?xml version="1.0" encoding="utf-8"?> <catalog>    <item >       <maker>Scratchmore</maker>       <description>Wool sweater</description>       <size>L</size>       <price>120.00</price>       <discount>0.10</discount>       <discountPrice>108.00</discountPrice>       <currency>USD</currency>    </item> </catalog>

The content of discount was taken from the content of the value element in discount. xml via the document( ) function. Because of this, the content in the output is 0.10 rather than 0.1 (it was 0.1 with variable.xsl). Because of format-number( ), the content of discountPrice is 108.00 rather than just 108. The second argument of format-number( ) (###.00) specifies that the number is to be formatted in the output with two places after the decimal point.

As you know, you can't change a value defined with variable, so what do you do if you want to change the value of the discount? You can use the param element.



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