Re: [xsl] How to sort a nodeset returned by key()?

Subject: Re: [xsl] How to sort a nodeset returned by key()?
From: "Olivier Mengué" <olivier.mengue@xxxxxxxxx>
Date: Tue, 8 Apr 2008 23:47:33 +0200
It looks like XML tags in my posts have been filtered by hotmail, so
I'm reposting.

2008/4/5, Dolmen ! <dolmen@xxxxxxxxxxx>:
>
>  Hi,
>
>  Short:
>  How can i sort a nodeset returned by key(), store it in a variable,
>  and still be able to compare its nodes with  nodes of the original
>  document ?
>
>  Long:
>
>  This is a transformation of my data set to an HTML table using rowspans.
>  I'm sorting my data, then I'm using a Muenchian grouping to group rows.
>
>  My problem is that the order of my sorted node set is not the same as
>  the order of the nodeset returned by key(). I have not found how to
>  reliably distinguish the first node of the group to output the
>  grouping cells in the right place.
>
>  I'm using xsltproc (from libxslt)
>
>  Here is an example using Steve Muench's data from
>  http://www.dpawson.co.uk/xsl/sect2/N7450.html#d11343e31
>
>  If I remove this sort, the XHTML, is clean, but the table is not sorted.
>

<demo>
  <salesman id="0001" name="Rick Peterson">
    <account id="act001" region="Midwest">Johnosn's Laundry</account>
    <account id="act002" region="Canada">Franks's Laundry</account>
    <account id="act003" region="Alaska">Mary's Laundry</account>
    <account id="act004" region="New Jersey">Bill's Laundry</account>
    <account id="act005" region="Midwest">Hammond's Laundry</account>
  </salesman>
  <salesman id="0003" name="Ty Coon">
    <account id="act006" region="Canada">Franks's Diner</account>
    <account id="act007" region="Midwest">Johnosn's Diner</account>
    <account id="act008" region="Canada">Hammond's Diner</account>
    <account id="act009" region="Alaska">Mary's Diner</account>
    <account id="act010" region="Alaska">Bill's Diner</account>
  </salesman>
</demo>

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    <xsl:output method="xml" indent="yes" encoding="UTF-8"
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";
omit-xml-declaration="yes" />
  <xsl:strip-space elements="*"/>

  <!--
  The output is completely broken as the result of key() is not in
  the same order as the for-each node set.
  -->



  <xsl:key name="accounts-by-region" match="/demo/salesman/account"
use="@region"/>

  <xsl:template match="/demo">
    <html>
    <head><title>Accounts ordered by region</title></head>
      <body>
        <table border="1" valign="top">
          <tr><th>Region</th><th>Account</th></tr>
          <xsl:for-each select="salesman/account">
              <xsl:sort select="@region"/>
              <xsl:sort select="."/>
              <xsl:variable name="brand-model" select="concat(brand, '
', model)"/>
              <tr>
                 <xsl:if test="count(. | key('accounts-by-region',
@region)[1]) = 1">
                   <td><xsl:attribute name="rowspan"><xsl:value-of
select="count(key('accounts-by-region',
@region))"/></xsl:attribute><xsl:value-of select="@region"/></td>
                 </xsl:if>
                 <td><xsl:value-of select="."/></td>
              </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>


Olivier Mengui.
http://o.mengue.free.fr/

Current Thread