home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book HomeJava and XSLTSearch this book

2.5. Looping and Sorting

As shown throughout this chapter, you can use <xsl:apply-templates ...> to search for patterns in an XML document. This type of processing is sometimes referred to as a " data driven" approach because the data of the XML file drives the selection process. Another style of XSLT programming is called "template driven," which means that the template's code tends to drive the selection process.

2.5.3. Looping and Sorting Examples

The easiest way to learn about looping and sorting is to play around with a lot of small examples. The code in Example 2-9 applies numerous different looping and sorting strategies to our list of presidents. Comments in the code indicate what is happening at each step.

Example 2-9. Looping and sorting

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html"/>
  <xsl:template match="/">
    <html>
      <body>
        <h1>Sorting Examples</h1>
        <xsl:apply-templates select="presidents"/>
      </body>
    </html>
  </xsl:template>
  <!--********************************************************************
      ** presidents template
      *****************************************************************-->
  <xsl:template match="presidents">
    <!--*****************************************************************
        ** Sorting using xsl:for-each
        **************************************************************-->
    <h2>All presidents sorted by first name using xsl:for-each</h2>
    <xsl:for-each select="president">
      <xsl:sort select="name/first"/>
      <xsl:apply-templates select="name"/>
    </xsl:for-each>
    <!--*****************************************************************
        ** Sorting using xsl:apply-templates
        **************************************************************-->
    <h2>All presidents sorted by first name using xsl:apply-templates</h2>
    <xsl:apply-templates select="president/name">
      <xsl:sort select="first"/>
    </xsl:apply-templates>
    <h2>All presidents sorted by date using xsl:apply-templates</h2>
    <xsl:apply-templates select="president/name">
      <xsl:sort select="../term/@from" data-type="number" order="descending"/>
    </xsl:apply-templates>
    <!--*****************************************************************
        ** Multi-field sorting
        **************************************************************-->
    <h2>Multi-field sorting example</h2>
    <xsl:apply-templates select="president/name">
      <xsl:sort select="last"/>
      <xsl:sort select="first" order="descending"/>
    </xsl:apply-templates>
    <!--*****************************************************************
        ** Nested xsl:for-each loops
        **************************************************************-->
    <h2>All presidents and vice presidents using xsl:for-each</h2>
    <ul>
      <xsl:for-each select="president">
        <xsl:sort select="name/first" order="descending"/>
        <li>
          <xsl:apply-templates select="name"/>
        </li>
        <ul>
          <xsl:for-each select="vicePresident">
            <xsl:sort select="name/first"/>
            <li>
              <xsl:apply-templates select="name"/>
            </li>
          </xsl:for-each>
        </ul>
      </xsl:for-each>
    </ul>
    <!--*****************************************************************
        ** Same as previous, only using xsl:apply-templates
        **************************************************************-->
    <h2>All presidents and vice presidents using xsl:apply-templates</h2>
    <ul>
      <xsl:apply-templates select="president">
        <xsl:sort select="name/first" order="descending"/>
      </xsl:apply-templates>
    </ul>
  </xsl:template>
  <!--*****************************************************************
      ** 'president' template, outputs the president's name and vice
      **             president's name.
      **************************************************************-->
  <xsl:template match="president">
    <li>
      <xsl:apply-templates select="name"/>
    </li>
    <ul>
      <xsl:for-each select="vicePresident">
        <xsl:sort select="name/first"/>
        <li>
          <xsl:apply-templates select="name"/>
        </li>
      </xsl:for-each>
    </ul>
  </xsl:template>
  <!--*****************************************************************
      ** name template, outputs first, middle, and last name
      **************************************************************-->
  <xsl:template match="name">
    <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
    <xsl:value-of select="first"/>
    <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
    <xsl:value-of select="middle"/>
    <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
    <xsl:value-of select="last"/>
    <br/>
  </xsl:template>
</xsl:stylesheet>

Notice that when applying a sort to <xsl:apply-templates>, that element can no longer be an empty element. Instead, one or more <xsl:sort> elements are added as children of <xsl:apply-templates>. You should also note that sorting cannot occur in the <xsl:template match="name"> element. The reason for this is simple: at the <xsl:apply-templates> end, you have a list of nodes to sort. By the time the processing reaches <xsl:template match="name">, the search has narrowed down to a single <name>, so there is no node list left to sort.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.