[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Sorting and grouping


Subject: Re: [xsl] Sorting and grouping
From: Joerg Heinicke <joerg.heinicke@xxxxxx>
Date: Mon, 30 Dec 2002 05:24:05 +0100

Hello Marshal,

(see comments inline)

Marshal Linfoot wrote:
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 -->

these both sorts are in the wrong place. You are sorting the "distinct-starters" by name. name is distinct, so they *are* sorted. Now you try to sort (only the distinct-starters) by dsort and tsort, but they are already sorted - so the last two sorts seem to have no effect. Remove it from here.


    </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)">

and place them here!! Here you apply templates to all schedule items/dates of this group.
<xsl:sort select="dsort"/>
<xsl:sort select="tsort"/>
</xsl:apply-templates>


</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.

Regards,


Joerg



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



Current Thread
Keywords
xsl