Like most programming languages, XSLT includes a few keywords to let you control
the flow of the processing. These include the if
/then
construct, while
loops and some extras. Like anything in XSLT,
these features are implemented as XML elements.
if
The if
element does one of the most common things in programming
– checking a condition and executing an action if the condition is met. A simple
example is:
<xsl:template match="AUTHOR">
<xsl:if test="@name">
<I><xsl:value-of select="@name"/></I>
</xsl:if>
</xsl:template>
The if
element has a test
attribute. If the XPath
expression in it returns false
(an empty node list), the content
of the element is not executed. In the example, the XPath query @name
returns true
if an attribute with name name
exists.
The if
element cannot be combined with an else
element
(as is common in many languages). If you need an else, you have to use the choose
/when
/otherwise
construct. Several if elements can be used nested.
choose/when/otherwise
For more complex choices the choose
, when
and otherwise
elements can be used. The elements when
and otherwise
can only be used within a choose
element. The processor will check
every when
element from the top down. A when
element
works exactly like an if
element. The first time the test
attribute returns true, the content of that when
element is executed.
After this, the processor jumps past the choose
element without
further checking. If none of the when
elements can be executed,
the otherwise
element will be executed (if there is one).
<xsl:template match="AUTHOR">
<xsl:choose>
<xsl:when test="@name = 'Duynstee'">
<B><xsl:value-of select="@name"/></B>
</xsl:when>
<xsl:when test="@name">
<I><xsl:value-of select="@name"/></I>
</xsl:when>
<xsl:otherwise>
No name available
</xsl:otherwise>
<xsl:choose>
</xsl:template>
In this example, the name
attribute of the AUTHOR
element we are processing is first checked for being 'Duynstee'. If it is, the
value of the attribute is generated in the output as content of a B
element and the processor jumps past the xsl:choose
element in
the stylesheet. If it is not, the next check is performed. If this is the case,
the value of the name attribute is generated as content of an I
element. If the second check fails too, then (and only then) will the processor
execute the content of the xsl:otherwise
element, which means generating
the string 'No name available'.
for-each
For looping through a set of nodes, XSLT specifies the for-each element. The
for-each
element has a select
attribute holding an
XPath expression. The content of the for-each
element is executed
for each result from this query. Inside the loop, the context is moved to the
current result set element.
<xsl:template match="PUBLISHER"><xsl:for-each select="child::BOOK">
<xsl:value-of select="attribute::title"/>
<xsl:for-each select="child::AUTHOR">
<xsl:value-of select="attribute::name"/>
</ xsl:for-each>
<xsl:text> </xsl:text>
<!—Insert a new line after each book -->
</ xsl:for-each>
</xsl:template>
In this example, for-each
elements are nested. Because the context
moves with the for-each
loop, the select
attribute
of the inner loop is evaluated in the context of the results of the outer loop.
This is of course what you would expect.
Note that there is not much difference between an apply-templates
element with an appropriate template and a for-each
loop. Basically,
a for-each
loop is an in-line template. However, a for-each
loop is generally more easy to read, but separating the content over several
templates makes reuse of the inner template easier.
sort
Whenever XSLT iterates along a set of nodes, it can be useful to set the order of iteration. By default this is always document order, but the destination format may expect another order (or you are transforming data to HTML and you need to display it in a set order).
Sorting can be used on the elements apply-templates
and for-each
.
The sort
element is inserted as a child element of the apply-templates
or for-each
element. Consider this example:
<xsl:template match="FAMILY">
<xsl:apply-templates select="PERSON">
<xsl:sort select="@lastname"/>
<xsl:sort select="@firstname"/>
</xsl:apply-templates>
</xsl:template>
The select
attribute holds an XPath expression. This expression
is evaluated for each of the nodes in the set. The result of this expression
determines the position in the sorted set.
By inserting multiple sort
elements, the result set can be sorted
primarily on the first criterion, and secondarily on the second one. In this
case, the apply-templates
element selects a set of all PERSON
elements. These are sorted first on their lastname
attribute, then
on their firstname
attribute. Only after the sorting does the XSLT
processor start searching for the appropriate matching templates.
A number of extra optional attributes can be used with the sort
element. The most important ones are:
-
order
, for specifying 'ascending
' or 'descending
' sort order. -
data-type
, for sortingnumerically
oralphabetically
. The default isalphabetically
, causing 10 to be smaller than 9. Available values fordata-type
are 'text
' and 'number
'. Other values can also be used, but the meaning is not specified by the XSLT specification. -
case-order
, for specifyinglower-first
orupper-first
. Whencase-order
islower-first
, A sorts after a. There is no functionality for case insensitivity.
Comments