xsl-list
[Top] [All Lists]

Re: Sorting and grouping

2002-12-29 21:24:05
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



<Prev in Thread] Current Thread [Next in Thread>