page 56
Chapter 4. Branching and Control Elements
So far, weve done some straightforward transformations and weve been able to do some reasonably sophisticated things. To do truly useful work, though, well need to use logic in
our stylesheets. In this chapter, well discuss the XSLT elements that allow you to do just that. Although youll see several XML elements that look like constructs from other
programming languages, theyre not exactly the same. As we go along, well discuss what makes XSLT different and how to do common tasks with your stylesheets.
4.1 Goals of This Chapter
By the end of this chapter, you should:
•
Know the XSLT elements used for branching and control
•
Understand the differences between XSLTs branching elements and similar constructs in other programming languages
•
Know how to invoke XSLT templates by name and how to pass parameters to them, if you want
•
Know how to use XSLT variables
•
Understand how to use recursion to get around the limitations of XSLTs branching and control elements
4.2 Branching Elements of XSLT
Three XSLT elements are used for branching:
xsl:if
,
xsl:choose
, and
xsl:for-each
. The first two are much like the
if
and
case
statements you may be familiar with from other languages, while the
for-each
element is significantly different from the
for
or
do-while
structures in other languages. Well discuss all of them here.
4.2.1 The xsl:if Element
The
xsl:if
element looks like this:
xsl:if test=countzone gt; 2 xsl:textApplicable zones: xsl:text
xsl:apply-templates select=zone xsl:if
The
xsl:if
element, surprisingly enough, implements an
if
statement. The element has only one attribute,
test
. If the value of
test
evaluates to the boolean value
true
, then all elements inside the
xsl:if
are processed. If
test
evaluates to
false
, then the contents of the
xsl:if
element are ignored. If you want to implement an if-then-else statement, check out the
xsl:choose
element described in the next section. Notice that we used
gt;
instead of in the attribute value. Youre always safe using
gt;
here, although some XSLT processors process the greater-than sign correctly if you use instead. If you need to use the less-than operator
, youll have to use the
lt;
entity. The same holds true for the less-than-or-equal operator
=
and the greater-than-or-equal
=
operators. See Section B.4.2
for more information on this topic.
page 57
4.2.1.1 Converting to boolean values
The
xsl:if
element is pretty simple, but its the first time weve had to deal with boolean values
. These values will come up later, so we might as well discuss them here. Attributes like the
test
attribute of the
xsl:if
element convert whatever their values happen to be into a boolean value. If that boolean value is
true
, the
xsl:if
element is processed. The
xsl:when
element, which well discuss in just a minute, has a
test
attribute as well. Heres the rundown of how various datatypes are converted to boolean values:
number If a number is positive or negative zero, it is
false
. If a numeric value is
NaN
not a number; if I try to use the string blue as a number, the result is
NaN
, it is
false
. If a number has any other value, it is
true
. node-set
An empty node-set is
false
, a non-empty node-set is
true
. string
A zero-length string is
false
; a string whose length is not zero is
true
. These rules are defined in Section 4.3 of the XPath specification.
4.2.1.2 Boolean examples
Here are some examples that illustrate how boolean values evaluate the
test
attribute:
xsl:if test=countzone gt;= 2
This is a boolean expression because it uses the greater-than-or-equal boolean operator. If the
count
function returns a value greater than or equal to 2, the
test
attribute is
true
. Otherwise, the
test
attribute is
false
.
xsl:if test=x
The variable
x
is evaluated. If it is a string, then the
test
attribute is
true
only if the string has a length greater than zero. If it is a node-set, then the
test
attribute is
true
only if the node-set has at least one member. If it is a number, then the
test
attribute is
true
only if the number is anything other than positive zero, negative zero, or
NaN
. Of course, if
x
is a boolean value,
true
is
true
and
false
is
false
.
xsl:if test=true
The boolean function
true
always returns the boolean value
true
. Therefore, this
test
attribute is always
true
.
xsl:if test=true
This example is a trick. This
test
attribute is
true
only if there is at least one
true
element in the current context. The XSLT processor interprets the value
true
as an XPath expression that specifies all
true
elements in the current context. The strings
true
and
false
dont have any special significance in XSLT.
xsl:if test=true
This
test
attribute is always
true
. Notice that in this case we used single quotes inside double quotes to specify that this is a literal string, not an element name. This
test
attribute is always
true
because the string has a length greater than zero, not because its value happens to be the word true.