XSLT for Dummies

 
Chapter 8 - Variables in XSLT: A Breed Apart
XSLT For Dummies
by Richard Wagner
Hungry Minds 2002
  

Variables play a less integral role in standard XSL transformations than their equivalents in C++ or Visual Basic do. But they remain useful devicesin particular, when you want to reuse values across your stylesheet and when you want to calculate values once and use the result in your output document.

Using a variable as a shortcut

Perhaps the most common purpose for XSLT variables is simply to use them as shortcuts to values that you intend to use multiple times across a document. For example, suppose that you have a standard footer that you want to place at the bottom of a result document that you produce. Save time and effort by defining a variable once, having it reference a chunk of HTML.

<xsl:variable name="footer"> <p><font size="8pt">Copyright (c)2001, Variably Speaking, Inc.</font></p> <p><font size="8pt">Send us email at <a href="mailto:feedback@variably.com">feedback@varia bly.com</a></font> </p> </xsl:variable>

To use this footer variable, I reference it using the xsl:value-of element,

<xsl:value-of select="$footer"/>

which outputs the following HTML in the result document.

<p><font size="8pt">Copyright (c)2001, Variably Speaking, Inc.</font></p> <p><font size="8pt">Send us email at <a href="mailto:feedback@variably.com">feedback@varia bly.com</a> <font></p>

These shortcut variables are very easy to define and use in your XSLT stylesheets. They come in especially handy when you need to use hard-to-remember constants such as HTML color -code values or special characters .

Variables also come in handy when you need to reuse a value within the same stylesheet. For example, suppose that I want to transform the following XML snippet:

<film name="Henry V"> <director>Kenneth Branagh</director> <writer>Kenneth Branagh, William Shakespeare</writer> <year>1989</year> <runtime>137</runtime> <sound>Stereo</sound> <genre>Drama</genre> <score>10.0</score> <mpaa>PG-13</mpaa> </film>

and output it into this HTML:

<p>Highest movies by score:</p> <b> <font color="FF0000" size="2">Henry V by Kenneth Branagh</font> </b> <br/> <i> <font color="FF0000" size="-2">Received a score of: 10.0</font> </i> <br/>

Looking at the resulting HTML, notice that the font color is used twice. And, although the two specified font sizes are different, theyre relative to each other. Therefore, in my XSLT stylesheet, I can use variables to represent both the font color and size.

<xsl:variable name="myfontcolor">FF0000</xsl:variable> <xsl:variable name="myfontsize" select="2"/>

To get the results for the first output section, I create a template rule for the director element, plugging in the myfontcolor and myfontsize variables.

<xsl:template match="director"> <p>Highest movies by score:</p> <b><font color="{$myfontcolor}" size="{$myfontsize}"> <xsl:value-of select="../@name"/> <xsl:text> by </xsl:text> <xsl:apply-templates/> </font></b><br/> </xsl:template>

For the score template rule, the myfontcolor variable is simply placed as is. However, because I want the font size of this text to be four increments smaller than the myfontsize value, I subtract one from the variable. The XSLT processor evaluates {$myfontsize - 4} as an XPath expression and uses the result of the expression ( -2 ) in the output document.

<xsl:template match="score"> <i><font size="{$myfontsize-4}"> Received a score of: <xsl:apply-templates/> </font></i><br/> </xsl:template>

The complete XSL stylesheet is shown below.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Define variables --> <xsl:variable name="myfontcolor">FF0000</xsl:variable> <xsl:variable name="myfontsize" select="2"/> <!-- Director template --> <xsl:template match="director"> <p>Highest movies by score:</p> <b><font size="{$myfontsize}" color="{$myfontcolor}"> <xsl:value-of select="../@name"/> <xsl:text> by </xsl:text> <xsl:apply-templates/> </font></b><br/> </xsl:template> <!-- Score template --> <xsl:template match="score"> <i><font size="{$myfontsize - 4}"> Received a score of: <xsl:apply-templates/> </font></i><br/> </xsl:template> <!-- Remove these elements from our results document --> <xsl:template match="year"/> <xsl:template match="writer"/> <xsl:template match="sound"/> <xsl:template match="genre"/> <xsl:template match="mpaa"/> <xsl:template match="runtime"/> </xsl:stylesheet>

See the results on the transformation in Internet Explorer in Figure 8-1.

Figure 8-1: Results of the XSLT transforma-tion.

Using a variable as a calculator

Because select attribute variables return expressions rather than ordinary text, theyre handy when you want a little more firepower and flexibility, such as the calculation of a value. Consider the following XML file in Listing 8-1.

Listing 8-1: films .xml

<films> <film name="Henry V"> <director>Kenneth Branagh</director> <writer>Kenneth Branagh, William Shakespeare</writer> <year>1989</year> <runtime>137</runtime> <sound>Stereo</sound> <genre>Drama</genre> <score>10.0</score> <mpaa>PG-13</mpaa> </film> <film name="Groundhog Day"> <director>Harold Ramis</director> <writer>Danny Rubin</writer> <year>1993</year> <runtime>101</runtime> <sound>Dolby</sound> <genre>Romantic Comedy</genre> <score>9.0</score> <mpaa>PG</mpaa> </film> <film name="Man for All Seasons"> <director>Fred Zinnemann</director> <writer>Robert Bolt</writer> <year>1966</year> <runtime>120</runtime> <sound>Mono</sound> <genre>Drama</genre> <score>8.0</score> <mpaa>PG</mpaa> </film> <film name="Field of Dreams"> <director>Phil Alden Robinson</director> <writer>W.P.Kinsella, Phil Alden Robinson</writer> <year>1988</year> <runtime>107</runtime> <sound>Dolby</sound> <genre>Drama</genre> <score>9.8</score> <mpaa>PG</mpaa> </film> <film name="Babette&apos;s Feast"> <director>Gabriel Axel</director> <writer>Gabriel Axel</writer> <year>1987</year> <runtime>102</runtime> <sound>Dolby</sound> <genre>Drama</genre> <score>9.5</score> <mpaa>PG</mpaa> </film> </films>

 

Calculate the total number of PG-rated films in the list and then assign that value to a variable. You can tackle that problem by first defining a variable that uses an XPath expression to return the desired films.

<xsl:variable name="pgFilms" select="//film[mpaa='PG']"/>

The pgFilms variable uses the //film[mpaa='PG'] expression to tell the processor, "Gimme all the <film> elements in the document that have an <mpaa> child with the value of PG ."

The pgFilms variable differs from others in that its value is not a string or number but rather a result tree fragment , or a collection of nodes that meet the stated requirements.

After you have a variable to represent the tree nodes, your next step is to declare a second variable that takes the value of the first to calculate the total number of PG films.

<xsl:variable name="totalNumOfPgFilms" select="count($pgFilms)"/>

In the preceding expression, the built-in XPath count() function adds up the total number of nodes contained in the result tree fragment stored in the pgFilms variable.

Keeping the output simple, you can use the variable like this:

<xsl:variable name="pgFilms" select="//film[mpaa='PG']"/> <xsl:variable name="totalNumOfPgFilms" select="count($pgFilms)"/> <xsl:template match="/"> <p>The total number of PG films: <xsl:value-of select="$totalNumOfPgFilms"/> </p> </xsl:template>

The end result in HTML is

The total number of PG films: 4

  
 
 
2000-2002    Feedback

Категории