Once you have read this section, you will have found out that its title is a bit deceptive. You, as a programmer, have certain expectations about a new programming language when you start learning it. One of them is that you expect it to be possible to store values in variables, change them and retrieve them later. Although XSLT has an element called variable, you actually cannot do much with it. This may sound unbelievable, but it is a result of the way XSLT works that you cannot have variables. This is a thing that beginner XSLT programmers have many difficulties grasping.
variable
A variable in XSLT is really not what we would call a variable in VB, but more like a constant. The syntax for declaring a variable is like this:
<xsl:variable name="x" select="2"/>
Or you can declare it like this:
<xsl:variable name="x">2</xsl:variable>
These syntaxes are equivalent, but note that the first example uses an XPath expression and the second one uses an included fragment of XML. This causes the first variable to hold the numeric value 2 and the second one the string value '2'.
The value of a variable
can be used in expressions and attribute
value templates. The reference to a variable
's value is done with
$variablename, for example:
<xsl:variable name="x" value="2"/>
...
<xsl:value-of select="item[$x]"/>
<xsl:variable name="author">
Teun Duynstee
</xsl:variable>
...<xsl:copy-of select="$author"/>
The copy-of
element is a convenient way to insert the value of
a variable into the output document.
A variable can be used both as a top-level element (child of the stylesheet
element) and at template level (descendant of a template
element). As a top-level element, the variable
can be used from
any place in the document. Within the template, the variable
can
be seen by all elements following the declaration (and their descendants).
In conclusion, the variable
element doesn't really live up to
its name, because it cannot change. There is no way to change the content. This
is done by design. The XSLT specification does not want to specify any order
for the evaluation of different nodes. By introducing changing values, it would
become relevant for the result whether a certain action is performed before
or after the change.
param
The param
element works very much like the variable
element. The param
element has a name
attribute and
a select attribute, but the select
attribute on the param element
is only a default value. If a value is passed, this replaces the value in the
select
attribute.
Passing a Parameter to a Template
If a template has a parameter defined, a value can be passed when the template
is executed (by apply-templates
or call-template
).
Suppose you have this template:
<xsl:template name="numbered-item">
<xsl:param name="format" select="1. "/>
<xsl:number format="{$format}"/>
<xsl:apply-templates/>
</xsl:template>
If you call it using call-template
, its index number would be
formatted numerically (1. ). But we could also have the same template output
the number in another format using the parameter format
(which
is used in the attribute value template in the number
element):
<xsl:template match="OL/LI"><xsl:call-template name="numbered-item">
<xsl:if test="@count = 'alpha'">
<xsl:with-param name="format" select="'a. '"/>
</xsl:if>
</xsl:call-template>
</xsl:template>
This template will match on LI
elements that have an OL
parent. The transformation of these elements is implemented in the template
'numbered-item
'. Only if the matched element has a count
attribute with value 'alpha
' does the template get called with
a passed parameter value. This will cause the called template to output the
number of the element in another format.
The with-param
element can be used as a child of call-template
and apply-templates
. The name
must be specified; the
value can also be specified with the content of the element (just like the variable
and param
elements can).
Passing a Parameter to a Stylesheet
Although the XSLT specification defines a way to declare global parameters,
nothing is mentioned about passing a parameter to the stylesheet. This depends
on the implementation of the library you use. The SAXON and XT implementations
both allow passing parameters on the command line. In the developers preview
of MSXML, you can set a parameter to a stylesheet only by using the special
XMLDOMXSLProcessor object. This object is new in the MSXML library and is intended
to cache compiled stylesheets to improve performance for repeated transforms
with the same stylesheet. If your stylesheet contains a parameter called $x
,
the following code could be used to make the transformation:
Dim oDoc as new MSXML2.DOMDocument
Dim oXSLT as new MSXML2.DOMDocument
Dim oResult as new MSXML2.DOMDocument
Dim oTemplate as new MSXML2.XSLTemplate
Dim oXMLDOMXSLProcessor as new MSXML2.XMLDOMXSLProcessor
oDoc.async = false
oXSLT.async = false
oDoc.load "http://www.comp.com/sourceDocument.xml"
oXSLT.load "http://www.comp.com/stylesheet.xsl"
Set oTemplate.stylesheet = oXSLT.documentElement
Set oXMLDOMXSLProcessor = oTemplate.createProcessor
Set oXMLDOMXSLProcessor.input = oDoc
Set oXMLDOMXSLProcessor.output = oResult
oXMLDOMXSLProcessor.addParameter("x", "Value we want to pass in")
oXMLDOMXSLProcessor.transform
There are quite a lot of objects that we need here, three DOMDocument
objects for starters. One of them may be empty. It is the target for the transform
(oResult
). The second one contains the source document (oDoc
)
and the third one contains the stylesheet (oXSLT
). oXSLT
is used to build the right template object. This template is used to create
an XMLDOMXSLProcessor
object. We inform the processor about the
input and output documents, and then finally add our parameter value and let
it transform. As this library is by no means stable at the time of writing –
it is only a preview after all – it is very possible (so indicates the preliminary
documentation) that the syntax will be different in the final release. In any
case, the functionality of passing parameters will be included in that
release.
Comments