Summary XPath: A Syntax for Describing Needles and Haystacks

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.