[xsl] Sorting and grouping

Subject: [xsl] Sorting and grouping
From: Marshal Linfoot <marshal@xxxxxxxx>
Date: Fri, 20 Dec 2002 14:54:08 -0500
I've been looking thru this list and searching google for examples of sorting and grouping in xsl. Just when I thought I had found an example that worked, on closer examination it is missing one little piece and now I'm completely baffled. I can't get it to sort on a second and third element.

I'd appreciate any advice/suggestions/pointers...

xml example----------
<schedule>

<classes type="Basic">
  <class>
    <name>Class BBB</name>
    <day>Sunday</day><dsort>7</dsort><dsort>7</dsort>
    <time>2:30pm to 4:00pm</time><tsort>1430</tsort>
  </class>
  <class>
    <name>Class AAA</name>
    <day>Monday</day><dsort>1</dsort>
    <time>7:30pm to 9:00pm</time><tsort>1930</tsort>
  </class>
  <class>
    <name>Class BBB</name>
    <day>Tuesday</day><dsort>2</dsort>
    <time>7:30pm to 9:00pm</time><tsort>1930</tsort>
  </class>
  <class>
    <name>Class AAA</name>
    <day>Wednesday</day><dsort>3</dsort>
    <time>5:00pm to 6:30pm</time><tsort>1700</tsort>
  </class>
  <class>
    <name>Class BBB</name>
    <day>Tuesday</day><dsort>2</dsort>
    <time>11:00am to 12:30pm</time><tsort>1100</tsort>
  </class>
</classes>
<classes type="Advanced">
  <class>
    <name>Class ZZZ</name>
    <day>Sunday</day><dsort>7</dsort><dsort>7</dsort>
    <time>2:30pm to 4:00pm</time><tsort>1430</tsort>
  </class>
  <class>
    <name>Class XXX</name>
    <day>Thursday</day><dsort>4</dsort>
    <time>7:00pm to 9:00pm</time><tsort>1900</tsort>
  </class>
  <class>
    <name>Class XXX</name>
    <day>Tuesday</day><dsort>2</dsort>
    <time>7:30pm to 9:00pm</time><tsort>1930</tsort>
  </class>
</classes>

</schedule>

Desired Output-------------
Basic Classes:
      Class AAA    Monday      7:30pm to 9:00pm
                   Wednesday   5:00pm to 6:30pm

      Class BBB    Tuesday     11:00am to 12:30pm
                   Tuesday     7:30pm to 9:00pm
                   Sunday      2:30pm to 4:00pm

Advanced Classes:
      Class XXX    Tuesday     7:30pm to 9:00pm
                   Thursday    7:00pm to 9:00pm

Class ZZZ Sunday 2:30pm to 4:00pm

The following XSL groups them okay so I can add space between the groups and remove the redundant class names, but it doesn't sort by day or time.

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


<xsl:output method="html"/>

  <!--
    Define a key for grouping classes by name.
  -->
  <xsl:key name="kName" match="class" use="name" />

  <xsl:template match="schedule">
    <xsl:apply-templates />
  </xsl:template>

<!--
Match the classes and group by class name.
Sort by class name, day, time
-->
<xsl:template match="classes">
<h3><xsl:value-of select="@type"/></h3>
<xsl:choose>
<xsl:when test="@type = 'Basic'">
<p>
<xsl:text>Basic Classes:</xsl:text>
</p>
</xsl:when>
<xsl:otherwise>
<p>
<xsl:text>Advanced Classes:</xsl:text>
</p>
</xsl:otherwise>
</xsl:choose>
<table>
<xsl:apply-templates select="class [generate-id() = generate-id(key('kName',name))]" mode="distinct-start">
<xsl:sort select="name"/>
<xsl:sort select="dsort"/> <!-- seems to ignore this -->
<xsl:sort select="tsort"/> <!-- and this -->
</xsl:apply-templates>
</table>
</xsl:template>


  <!--
    Match the first class in the group.
    Output all columns.
  -->
  <xsl:template match="class" mode="distinct-start">
    <tr>
    <td><xsl:apply-templates select="name"/></td>
    <td><xsl:apply-templates select="day"/></td>
    <td><xsl:apply-templates select="time"/></td>
    </tr>
    <xsl:apply-templates select="key('kName',name)" />
  </xsl:template>

  <!--
    Match the other classes in the group.
    Output blank class name and other columns.
  -->
  <xsl:template match="class">
    <xsl:if test="not(generate-id() = generate-id(key('kName',name)))">
      <tr>
      <td><xsl:text>&#160;</xsl:text></td>
      <td><xsl:apply-templates select="day"/></td>
      <td><xsl:apply-templates select="time"/></td>
      </tr>
    </xsl:if>
      <xsl:if test="position() = last()">
       <tr><td><xsl:text>&#160;</xsl:text></td></tr>
      </xsl:if>
  </xsl:template>

</xsl:stylesheet>

Thanks in advance for any ideas.
--
Marshal Linfoot	


XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread