Re: [xsl] Alphabetic sort retaining first letters as Headers

Subject: Re: [xsl] Alphabetic sort retaining first letters as Headers
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 1 Nov 2004 20:59:52 +0000
Hi Dave,

> I have been trying to sort and display a a set of elements
> alphabetically and grab the first letter for a group header. The
> header would only appear once and won't appear if there is an empty
> set (eg. 'X').

This is a grouping problem. Using the Muenchian method for grouping,
you should do this:

First, define a key that indexes each of the elements using the first
letter of the element:

<xsl:key name="elements" match="element" use="substring(., 1, 1)" />

This means you can get all the elements that begin with 'B', using:

  key('elements', 'B')

You can then access the first element of each group using:

  element[generate-id(.) =
          generate-id(key('elements', substring(., 1, 1))[1])]

If I understand what you're after correctly, the code for your actual
problem should look something like:

<xsl:key name="maps" match="maps | maptitle"
         use="substring(., 1, 1)" />

<xsl:template match="body" mode="alpha-title">
  <xsl:for-each
    select="(part/chapters/mapunits/maps |
             part/chapters/mapunits/maptitle)
              [generate-id(.) =
               generate-id(key('maps', substring(., 1, 1))[1])]">
    <xsl:sort select="." />
    <xsl:variable name="firstletter" select="substring(., 1, 1)" />
    <div class="trackNumber">
      <xsl:value-of select="$firstletter" />
    </div>
    <xsl:for-each select="key('maps', $firstletter)">
      <div class="mapTitle">
        <a href="../../Maps/{../../@chap}/{../@mapunitNumber}/{@mapNumber}/Normal/">
          <xsl:value-of select="." />
        </a>
      </div>
    </xsl:for-each>
  </xsl:for-each>
</xsl:template>

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/

Current Thread