Flow Control

In this lesson of the XSLT tutorial, you will learn...
  1. How to implement flow control in XSLT.
  2. How to loop through XPath result-sets.
  3. How to sort results.
  4. How to write if statements in XSLT.
  5. How to use xsl:choose for more complicated conditionals.

Looping in XSLT

The tag for looping in XSLT is <xsl:for-each>. It takes the select attribute, which uses XPath to point to a node-set and it outputs the contents of the xsl:for-each one time for each node in the set.

Code Sample: FlowControl/Demos/BeatlesForEach.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
 <html>
  <head>
   <title>Beatles</title>
  </head>
  <body>
   <table border="1">
   <xsl:for-each select="beatles/beatle">
    <tr>
    <td><a href="{@link}"><xsl:value-of select="name/lastname"/></a></td>
    <td><a href="{@link}"><xsl:value-of select="name/firstname"/></a></td>
    </tr>
   </xsl:for-each>
   </table>
  </body>
 </html>
</xsl:template>

</xsl:stylesheet>
Code Explanation

In the code above, you will also notice that the Beatles' first and last names are made into links. The value of the href attribute of the <a> tag is {@link}. This is the equivalent of <xsl:value-of select="@link"/>. However, it would not be well-formed XML to place the <xsl:value-of /> tag (or any tag, for that matter) inside the angle brackets of another open tag, so the curly-bracket syntax is used instead. The output in a browser would look like this.

Sorting with XSLT

The tag for sorting in XSLT is <xsl:sort>, which takes the select attribute with a value of an XPath to identify the node to sort by. The xsl:sort element can also take the order attribute, which has two possible values: ascending (the default) and descending.

Code Sample: FlowControl/Demos/BeatlesSort.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
 <html>
  <head>
   <title>Beatles</title>
  </head>
  <body>
   <table border="1">
   <xsl:for-each select="beatles/beatle">
    <xsl:sort select="name/lastname" order="descending"/>
    <tr>
    <td><a href="{@link}"><xsl:value-of select="name/lastname"/></a></td>
    <td><a href="{@link}"><xsl:value-of select="name/firstname"/></a></td>
    </tr>
   </xsl:for-each>
   </table>
  </body>
 </html>
</xsl:template>

</xsl:stylesheet>
Code Explanation

Notice that the xsl:sort is nested within an xsl:for-each element. This is very common as xsl:sort elements need to be nested within repeating structures.

When FlowControl/Demos/BeatlesSort.xml is transformed against FlowControl/Demos/BeatlesSort.xsl, the output is the same as it would be when transformed against FlowControl/Demos/BeatlesForEach.xsl , except the results are sorted by last name in descending order.

Conditions with XSLT

xsl:if

The <xsl:if> tag is used to create a simple if condition. Its test attribute holds the condition, which is written in the form of an XPath, often using the XPath operators in the "XPath Operators" table.

Code Sample: FlowControl/Demos/BeatlesIf.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
 <html>
  <head>
   <title>Beatles</title>
  </head>
  <body>
   <table border="1">
   <tr>
    <th>First Name</th>
    <th>Last Name</th>
   </tr>
   <xsl:for-each select="beatles/beatle">
    <xsl:sort select="name/lastname" />
    <xsl:if test="not(@real='no')">
    <tr>
    <td><xsl:value-of select="name/firstname"/></td>
    <td><xsl:value-of select="name/lastname"/></td>
    </tr>
    </xsl:if>
   </xsl:for-each>
   </table>
  </body>
 </html>
</xsl:template>

</xsl:stylesheet>
Code Explanation

The xsl:for-each loop causes XSLT to look at each beatle element. The nested xsl:if element uses XPath to test to see if the value of real attribute of the beatle element is no. It then negates the result with the not() function. This way beatle elements that have no real attribute and beatle elements that do have a real attribute with the value of ANYTHING BUT no will both be included in the result set.

When FlowControl/Demos/BeatlesIf.xml is transformed against FlowControl/Demos/BeatlesIf.xsl, the output looks like this in a browser.

Note that there are no <xsl:else> or <xsl:elseif> elements.

xsl:choose

For multi-level conditions, <xsl:choose> is used. It takes as children one or more <xsl:when> tags with an optional <xsl:otherwise> tag at the end.

Code Sample: FlowControl/Demos/BeatlesChoose.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
 <html>
  <head>
   <title>Beatles</title>
  </head>
  <body>
   <table border="1">
   <tr>
    <th>First Name</th>
    <th>Last Name</th>
   </tr>
   <xsl:for-each select="beatles/beatle">
    <xsl:sort select="name/lastname" />
    <xsl:choose>
    <xsl:when test="not(@real='no')">
    <tr bgcolor="red">
    <td><xsl:value-of select="name/firstname"/></td>
    <td><xsl:value-of select="name/lastname"/></td>
    </tr>
    </xsl:when>
    <xsl:otherwise>
    <tr bgcolor="orange">
    <td><s><xsl:value-of select="name/firstname"/></s></td>
    <td><s><xsl:value-of select="name/lastname"/></s></td>
    </tr>
    </xsl:otherwise>
    </xsl:choose>
   </xsl:for-each>
   </table>
  </body>
 </html>
</xsl:template>

</xsl:stylesheet>
Code Explanation

This code ouputs a table row with a red background for every real Beatle and a table row with an orange background for every fake Beatle. The fake Beatles are also crossed out with the <s> tag.

When FlowControl/Demos/BeatlesChoose.xml is transformed against FlowControl/Demos/BeatlesChoose.xsl, the output looks like this in a browser.

Flow Control Conclusion

In this lesson of the XSLT tutorial, you learned how loop through nodesets and how to adjust the output of an XSLT based on conditions.

To continue to learn XSLT go to the top of this page and click on the next lesson in this XSLT Tutorial's Table of Contents.

Use of this website implies agreement to the following:

Copyright Information

All pages and graphics on this Web site are the property of Webucator, Inc. unless otherwise specified.

None of the content on this website may be redistributed or reproduced in any way, shape, or form without written permission from Webucator, Inc.

No Printing or saving of web pages

This content may not be printed or saved. It is for online use only.


Linking to this website

You may link to any of the pages on this website; however, you may not include the content in a frame or iframe without written permission from Webucator, Inc.


Warranties

This website is provided without warranty of any kind. There are no guarantees that use of the site will not be subject to interruptions. All direct or indirect risk related to use of the site is borne entirely by the user. All code and explanations provided on this site are provided without warranties to correctness, performance, fitness, merchantability, and/or any other warranty (whether expressed or implied).

For individual private use only

You agree not to use this online manual to deliver or receive training. If you are delivering or attending a class that is making use of this online manual, you are in violation of our terms of service. Please report any abuse to courseware@webucator.com. If you would like to deliver or receive training using this manual, please fill out the form at http://www.webucator.com/Contact.cfm.