for-each select=//address[generate-id(.)=generate-id(key(zipcodes, zip)[1])] : for each « XSLT stylesheet « XML Tutorial






File: Data.xml

<?xml version="1.0"?>
<addressbook>

  <address>
    <name>
      <title>Ms.</title>
      <first-name>Doris</first-name>
      <last-name>Smith</last-name>
    </name>
    <street>707 New Way</street>
    <city>New York</city>
    <state>ME</state>
    <zip>00218</zip>
  </address>
  <address>
    <name>
      <first-name>Jane</first-name>
      <last-name>Lee</last-name>
    </name>
    <street>283 First Avenue</street>
    <city>Big City</city>
    <state>MA</state>
    <zip>02718</zip>
  </address>
</addressbook>

File: Transform.xslt

<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="html" indent="no"/>

  <xsl:key name="zipcodes" match="address" use="zip"/>

  <xsl:template match="/">
    <table border="1">
      <xsl:for-each select="//address[generate-id(.)=generate-id(key('zipcodes', zip)[1])]">
        <xsl:sort select="zip"/> 
        <xsl:for-each select="key('zipcodes', zip)">
          <xsl:sort select="name/last-name"/>
          <xsl:sort select="name/first-name"/>
          <tr>
            <xsl:if test="position() = 1">
              <td valign="center" bgcolor="#999999">
                <xsl:attribute name="rowspan">
                  <xsl:value-of select="count(key('zipcodes', zip))"/>
                </xsl:attribute>
                <b>
                  <xsl:text>Zip code </xsl:text><xsl:value-of select="zip"/>
                </b>
              </td>
            </xsl:if>
            <td align="right">
              <xsl:value-of select="name/first-name"/>
              <xsl:text> </xsl:text>
              <b><xsl:value-of select="name/last-name"/></b>
            </td>
            <td>
              <xsl:value-of select="street"/>
              <xsl:text>, </xsl:text>
              <xsl:value-of select="city"/>
              <xsl:text>, </xsl:text>
              <xsl:value-of select="state"/>
              <xsl:text> </xsl:text>
              <xsl:value-of select="zip"/>
            </td>
          </tr>
        </xsl:for-each>
      </xsl:for-each>
    </table>
  </xsl:template>

</xsl:stylesheet>

Output:

<table border="1"><tr><td valign="center" bgcolor="#999999" rowspan="1"><b>Zip code 00218</b></td><td align="right">Doris <b>Smith</b></td><td>707 New Way, New York, ME 00218</td></tr><tr><td valign="center" bgcolor="#999999" rowspan="1"><b>Zip code 02718</b></td><td align="right">Jane <b>Lee</b></td><td>283 First Avenue, Big City, MA 02718</td></tr></table>








5.45.for each
5.45.1.The xsl:for-each element allows all nodes in a node-set to be processed according to the XSLT instructions nested inside the xsl:for-each element.
5.45.2.Nested for-each loop with sorting
5.45.3.Output xml elements in for-each loop
5.45.4.for-each select=preceding-sibling::address[zip=./zip]
5.45.5.for-each select=//address[generate-id(.)=generate-id(key(zipcodes, zip)[1])]
5.45.6.Use for-each loop to output list items
5.45.7.for-each select="addressbook/address" and sort
5.45.8.compares sorted and unsorted xsl:for-each element
5.45.9.xsl:for-each instruction contains a template, which is applied to each node selected with select attribute.