The xsl:if Element
All programming languages contain a construct to test for an item that can be only either true or false. If the value is true, a section of code is executed. If it's false, the first section is skipped, and another section may or may not be executed. In JavaScript, the construct is an if-else statement. The else part is optional. If your goal is to execute a segment of code when the value is true and do nothing otherwise, the else is not included.
In XSL, you can use the xsl:if command to construct an expression that will control the conditional execution of a block of XSL code. The delimiters of the block of code are the opening and closing <xsl:if> tags. There's no companion xsl:else command, although it can be mimicked in an awkward manner. For example, consider the following if construct:
<xsl:if match="Author[Name='Charles Ashbacher']"> </xsl:if>
The if equivalent for the else would be as follows:
<xsl:if match="Author[Name!='Charles Ashbacher']"> </xsl:if>
An xsl:if Example That Will Read the Catalog Database and Extract the Book Records with a BestSeller Attribute
The first example, Listing 15.1, demonstrates how to use xsl:if to selectively extract and display information from an XML file. The data file that you'll use is listing14-4.xml. Note that this is the <Catalog> database with the BestSeller attribute added to the <Book> tag.
NOTE
The source code used in this chapter, including listing14-4.xml, can be downloaded from the Sams Publishing Web site, http://www.mcp.com/sams/display_sams.cfm?item=0672319500&itemhdr=Source%20Code&itemloc=sourcecode. See the Chapter 15 folder.
Listing 15.1 An xsl:if Conditional That's True If the Book Record Has a BestSeller Attribute
1: <?xml version="1.0"?> 2: <!-- This file is an XSL style sheet file that is used to 3: read the data from the simple book catalog database. 4: In this case, the data will be sorted when read, and 5: we are using conditional XSL elements to filter the 6: data. 7: --> 8: <xsl:stylesheet xmlns:xsl="uri:xsl"> 9: <xsl:template match="/"> 10: <html> 11: <body> 12: <table border="1"> 13: <tr style="font-weight:bold;color:blue"> 14: <td>Author Name</td> 15: <td>Author Address</td> 16: <td>Author City</td> 17: <td>Author State</td> 18: <td>Author e-mail</td> 19: <td>Publisher Name</td> 20: <td>Publisher Address</td> 21: <td>Publisher Phone</td> 22: </tr> 23: <xsl:for-each select="Catalog/Book" order-by="+Author/City"> 24: <xsl:if match=".[@BestSeller]"> 25: <tr> 26: <xsl:apply-templates/> 27: </tr> 28: </xsl:if> 29: </xsl:for-each> 30: </table> 31: </body> 32: </html> 33: </xsl: template> 34: <xsl:template match="Author"> 35: <td><xsl:value-of select="Name"/></td> 36: <td><xsl:value-of select="Address"/></td> 37: <td><xsl:value-of select="City"/></td> 38: <td><xsl:value-of select="State"/></td> 39: <td><xsl:value-of select="Email"/></td> 40: </xsl:template> 41: <xsl:template match="Publisher"> 42: <td><xsl:value-of select="Name"/></td> 43: <td><xsl:value-of select="Address"/></td> 44: <td><xsl:value-of select="Phone"/></td> 45: </xsl:template> 46: </xsl: stylesheet>
Run the file in IE and note that only the entries where the BestSeller attribute is assigned a value are displayed. The output is illustrated in Figure 15.1.
Figure 15.1 The output of Listing 1.
This result is the consequence of the xsl:if, where the code guarded by the if is executed only when the following is true:
match=".[@BestSeller]"
This is the syntax for the presence of the BestSeller attribute. Of course, if the attribute is present, the following line is executed and the data is extracted:
<xsl:apply-templates/>
Because there's no alternative, nothing is done when there's no BestSeller attribute.
Note that the code guarded by the if is delimited by the following tags:
<xsl:if . . . > </xsl:if>
An xsl:if Example That Selects Only the Records Where the BestSeller Attribute Has a Specific Value
Go back to Listing 15.1 and change this line
<xsl:if match=".[@BestSeller]">
to this:
<xsl:if match=".[@BestSeller='yes']">
This is the notation for selecting only those cases where the BestSeller attribute is assigned the value yes. Save the file before continuing.
View listing 14-4.html in IE 5. The output will be the only entry where BestSeller is assigned a value of yes. This is illustrated in Figure 15.2.
Figure 15.2 Extracting only the bestsellers.
Using Multiple xsl:if Elements in an XSL File
If you're dealing with an attribute with more than one possible value, you can handle each of the possibilities by using an additional <xsl:if>. Listing 15.2 demonstrates the use of more than one xsl:if inside an XSL file.
Listing 15.2 Using Multiple xsl:if Elements in an XSL File
1: <?xml version="1.0"?> 2: <!-- This file is an XSL style sheet file that is used to read the data from the 3: simple book catalog database. In this case, the data will be sorted when read, and 4: we are using conditional XSL elements to filter the data. 5: The filename is listing15-2.xsl. --> 6: <xsl:stylesheet xmlns:xsl="uri:xsl"> 7: <xsl:template match="/"> 8: <html> 9: <body> 10: <table border="1"> 11: <tr style="font-weight:bold;color:blue"> 12: <td>Author Name</td> 13: <td>Author Address</td> 14: <td>Author City</td> 15: <td>Author State</td> 16: <td>Author e-mail</td> 17: <td>Publisher Name</td> 18: <td>Publisher Address</td> 19: <td>Publisher Phone</td> 20: </tr> 21: <xsl:for-each select="Catalog/Book" order-by="+Author/City"> 22: <xsl:if match=".[@BestSeller='yes']"> 23: <tr> 24: <xsl:apply-templates/> 25: </tr> 26: </xsl:if> 27: <xsl:if match=".[@BestSeller='no']"> 28: <tr style="font-weight:bold;color:red"> 29: <td>Not a bestseller</td> 30: </tr> 31: </xsl:if> 32: </xsl:for-each> 33: </table> 34: </body> 35: </html> 36: </xsl: template> 37: <xsl:template match="Author"> 38: <td><xsl:value-of select="Name"/></td> 39: <td><xsl:value-of select="Address"/></td> 40: <td><xsl:value-of select="City"/></td> 41: <td><xsl:value-of select="State"/></td> 42: <td><xsl:value-of select="Email"/></td> 43: </xsl:template> 44: <xsl:template match="Publisher"> 45: <td><xsl:value-of select="Name"/></td> 46: <td><xsl:value-of select="Address"/></td> 47: <td><xsl:value-of select="Phone"/></td> 48: </xsl:template> 49: </xsl: stylesheet>
Modify listing14-2.html so that listing15-2.xsl is the XSL file opened. The output when the file is viewed in IE is illustrated in Figure 15.3.
Figure 15.3 Outputting a simple message when the BestSeller attribute is no.
The XML data file has two different values assigned to the BestSeller attribute, yes and no. This example includes two different xsl:if elements, one for each possible value of the BestSeller. The output when it was no was rather crude, consisting of a message in red. Because the only point was to demonstrate the difference, this was acceptable.
If an attribute can have several values, it's possible to include an xsl:if element for every one. However, this rapidly becomes awkward and difficult to understand. The solution is to create a multiple alternative construct using a combination of xsl:choose, xsl:when, and xsl:otherwise elements.