WebReference.com - Chapter 7 of XML for ASP.NET Developers, from Sams Publishing (8/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[. < 11])"/>
<xsl:template match="golfer">
<!-- ...Other content here -->
<td width="12%" align="left">
<xsl:value-of select="@handicap"/>
<br/>
<xsl:if test="@handicap > 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> </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 thexsl:attribute
element. As another example, if you had an attribute namedwidth
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="https://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"/>
 
<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 namedCustomerID
(shown earlier) has a parameter value ofALFKI
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 namedALFKI
(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 documentsall with different structures.
[previous] [next] |
© Copyright Pearson Education and
Created: April 22, 2002
Revised: April 22, 2002
URL: https://webreference.com/authoring/languages/xml/aspnet/chap7/8.html