WebReference.com - Chapter 7 of XML for ASP.NET Developers, from Sams Publishing (8/13) | WebReference

WebReference.com - Chapter 7 of XML for ASP.NET Developers, from Sams Publishing (8/13)

To page 1To page 2To page 3To page 4To page 5To page 6To page 7current pageTo page 9To page 10To page 11To page 12To page 13
[previous] [next]

XML for ASP.NET Developers

Using Variables and Parameters: The xsl:variable and xsl:param Elements

As programmers, we all take for granted the capability to use variables and pass parameters to functions. In fact, it's hard to imagine programming without variables and parameters. Most programmers would be hard pressed to eliminate them from their applications. Fortunately, there's no need to worry about variables or parameters being eliminated from C#, VB.NET, or even from languages such as XSLT. The XSLT specification includes the capability to use a variable or pass a parameter to a template. In this section, you are provided with a general overview of how variables and parameters can be used to make your XSLT documents more flexible. Let's first take a look at how variables can be used.

Variables in XSLT

XSLT variables are used to avoid calculating the same result multiple times. Although very similar to variables used in C# or any other programming language, XSLT variables can be set once but cannot be updated after they are set. The value assigned to a variable is retained until the variable goes out of scope. What, you say! XSLT variables can be set only once? Doesn't this make them the equivalent of a constant?

There's a method to the madness that makes perfect sense when analyzed. Because XSLT relies on templates that can be called randomly, depending on the structure of the source XML document, the capability to update a particular global variable could introduce problems. These types of problems are referred to as "side effects," and the XSLT specification eliminates the problem by allowing for no side effects. If you've ever stepped into a project that you didn't originally code that had bugs cropping up because of overuse of global variables, you'll appreciate this concept.

To illustrate the concept of side effects more, let's take a look at a simple example. If a template named template1 relies on another template named template2 to update the value of a global variable, what happens if template2 doesn't ever get processed? The rather obvious answer is that the global variable will never be updated and therefore can cause potential problems to template1 when it is processed. By not allowing variables in XSLT style sheets to be updated, this problem is avoided.

It's important to realize that XSLT documents can be written without the use of variables. However, variables can aid in cleaning up the code and can also result in more efficient XSLT style sheets. The following example uses a portion of the code shown earlier in Listing 7.4 to demonstrate how a variable declared globally (as a child element of the xsl:stylesheet element) can be used in XSLT:

<xsl:variable name="count" select="count(//@handicap[. &lt; 11])"/>

<xsl:template match="golfer">
  <!-- ...Other content here -->
  <td width="12%" align="left">
    <xsl:value-of select="@handicap"/>
    <br/>
    <xsl:if test="@handicap &gt; 11">
      <xsl:value-of select="$count"/> golfers have lower handicaps
    </xsl:if>
  </td>
  <!-- ...Other content here -->
</xsl:template>

The xsl:variable element can have a name and a select attribute. The name attribute is required and serves the obvious purpose of assigning a name that can be used to reference the variable. The select attribute is optional but when listed, must contain a valid XPath expression.

So what have we gained by using a variable in this template? The code has actually been made much more efficient as compared to writing the same code without using the variable. Instead of having to calculate the count of all the golfers in the XML document with handicaps less than 11 each time a golfer node template is matched, the variable obtains this value and stores it when the XSLT style sheet is first loaded. The variable can then be referenced in several places by adding the $ character to the beginning of the variable name ($count in this case). Doing this cuts out unnecessary processing during the transformation process.

At times, the value of an attribute may need to be dynamically generated and used in several places. In many cases, using a variable can make this process easier:

<xsl:variable name="color">
  <xsl:choose>
    <xsl:when test="@handicap = 10">
      #ff0000
    </xsl:when>
    <xsl:when test="@handicap = 20">
      #ffff00
    </xsl:when>
    <xsl:otherwise>
      #ffffff
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<font color="{$color}"><xsl:value-of select="@handicap"/></font>
<p>&#xa0;</p>
<font color="{$color}" size="4"><xsl:value-of select="lastName"/></font>

Although the value of the color attribute found on the font tag could be added by using the xsl:attribute element multiple times, by defining the value once in the variable, the code is kept cleaner and the processing is more efficient.


Tip

The previous example shows a shortcut that can be used to embed data directly into attributes that will be written out to the result tree. By wrapping a variable (or other item) with the { and } brackets, it will dynamically be added to the result tree. This is in contrast to adding the attribute name and value to a tag by using the xsl:attribute element. As another example, if you had an attribute named width in an XML document, you could write it out to a table tag by doing the following: <table width="{@width}">. This is similar to doing something such as <table width="<%=myWidth%>"> in ASP.NET.


Variables can also be useful for storing values returned by calling a template. This process will be shown a little later after you're introduced to the xsl:param element.

Parameters in XSLT

Parameters are useful in a variety of programming languages, with XSLT being no exception. Parameters can be used in XSLT documents in two basic ways. First, parameter values can be passed in from an ASP.NET application. This allows data not found within the XML document or XSLT style sheet to be part of the transformation process. Second, parameter values can be passed between XSLT templates in much the same way that parameters can be passed between functions in C# or VB.NET. You'll see how parameters can be used in both ways later in the chapter.

Declaring a parameter is similar to declaring a variable. Simply name the parameter and add an optional select attribute:

<xsl:param name="myParam" select="'My Parameter Value'"/>

As with variables, parameters can be children of the xsl:stylesheet or xsl:transform elements and can also be children of the xsl:template element. So when would you want to use a parameter? Let's assume that the golfers XSLT document shown in Listing 7.4 needs to show a specific golfer based on user input in a Web form. To accomplish this task, the ASP.NET application can pass in the value entered by the user to a parameter within the XSLT document. This value can then be used to display the proper golfer's information. A simplified document that uses a parameter named golferNum is shown next:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 version="1.0">
 <xsl:param name="golferName" select="'Dan'"/>
  <xsl:template match="golfers">
    <xsl:apply-templates select="//golfer[name/firstName=$golferName]"/>
  </xsl:template>
  <xsl:template match="golfer">
    <xsl:apply-templates/>
  </xsl:template>
  <xsl:template match="name">
    <xsl:value-of select="firstName"/>
    &#xa0;
    <xsl:value-of select="lastName"/>
  </xsl:template>
</xsl:stylesheet>

Having this parameter in the XSLT style sheet will cause a specific golfer's information to be transformed. Any other golfers in the XML document will simply be ignored. How is this accomplished? A small change was made to the xsl:apply-templates element in the golfers template. Instead of processing all golfer nodes in the XML document, the XPath expression in the select attribute specifies the specific golfer node to process:

<xsl:apply-templates select="//golfer[name/firstName=$golferName]"/>

Although this example hard-codes a value for the golferName parameter, an ASP.NET page would normally pass the value in using specific classes in the System.Xml assembly. You'll be introduced to these classes later in the chapter. If the value passed into the golferName parameter from the ASP.NET page does not match up with an existing golfer node in the XML document, no error will be raised.

Parameters can also be used in conjunction with the xsl:call-template element. Fortunately, from working with other programming languages, you already have a good understanding of how this works. Imagine calling a method named GetOrders() that accepts a single parameter as an argument. The method call would look something like the following:

GetOrders("ALFKI");

Now imagine that GetOrders is the name of an XSLT template used to transform an XML document containing customers and orders. Calling the template and passing the parameter can be accomplished by doing the following:

<xsl:template match="Customer">
  <xsl:call-template name="GetOrders">
    <xsl:with-param name="CustomerID" select="@CustomerID"/>
  </xsl:call-template>
</xsl:template>
<xsl:template name="GetOrders">
  <xsl:param name="CustomerID" select="'ALFKI'"/>
  <xsl:value-of select="//Order[@CustomerID = $CustomerID]"/>
</xsl:template>

This example shows the use of the xsl:call-template and xsl:with-param elements to initiate the template call. The xsl:call-template element has a single attribute that provides the name of the template to call. The xsl:with-param element has two attributes. One is used to name the parameter that data will be passed to and the other provides the value that is to be passed. The select attribute can contain any valid XPath expression. The xsl:with-param element can only be a child of the xsl:call-template or xsl:apply-templates element.


Tip

The xsl:param element named CustomerID (shown earlier) has a parameter value of ALFKI with single quotes around it because it is a string value rather than an XPath expression. Had the single quotes been omitted, the XSLT processor would try to find a node named ALFKI (which doesn't exist, of course). Although this seems fairly obvious, it's an easy mistake to make.


The xsl:param element in the template being called is updated by using the xsl:with-param element shown previously. It has two potential attributes, including name and select, as described earlier. In the previous example, the parameter named CustomerID is assigned a default value of ALFKI. This value will be overridden when the GetOrders template is called and a parameter value is passed to it using the xsl:with-param element.

Because variables cannot be updated in XSLT, parameters play a large role in allowing values to be passed between templates. A global parameter (declared as a child of the xsl:stylesheet or xsl:transform elements) can receive input from an ASP.NET page, but it cannot be updated more than once after processing of the XSLT document begins. However, the capability to place parameters within the scope of a specific template body offers the capability to call templates recursively. This is possible because a single template can call itself and pass a parameter value (or more than one value, in the case of multiple parameters within the template) that can then be processed as appropriate.

Although the inability to update variables and parameters may seem somewhat restrictive, the authors of the XSLT specification knew that it was necessary because XML documents can contain many different structures. You can't depend on one template being processed before another, especially in the case where one XSLT document is used to transform a variety of XML documents—all with different structures.


To page 1To page 2To page 3To page 4To page 5To page 6To page 7current pageTo page 9To page 10To page 11To page 12To page 13
[previous] [next]

© Copyright Pearson Education and Created: April 22, 2002
Revised: April 22, 2002

URL: http://webreference.com/authoring/languages/xml/aspnet/chap7/8.html