Re: Grouping with XSL...

Subject: Re: Grouping with XSL...
From: Marcus Groeber <mgroeber@xxxxxxxxxxxxxx>
Date: Tue, 28 Dec 1999 14:52:08 +0100
Paul Levin wrote:

>     Yes, I needed to do the same thing.  Thanks to David Carlisle (from this
> discussion group) I am using something like the following XSL --
>
> <xsl:for-each select="//COUNTRYCODE[not(. = following::COUNTRYCODE)]">
> <xsl:sort/>
> <H1><xsl:value-of select="."/></H1>
> <xsl:for-each select="//RECORD[.//COUNTRYCODE=current()]">
> <xsl:sort select="any field"/>
>
>        output your record
>
> </xsl:for-each>
> </xsl:for-each>

Adding more to the apparently never ending tale of XSL sorting/grouping...

This was also the first approach for tackling a similar problem (albeit with only
one level of sorting) in one of my projects, because it looked a lot more
straightforward and standards-compliant than the ingenious solution given by James
Clark in his xt:node-set example. [As you can see from this reference, all the
following has been tested with the 991105 version of James' XT.]

It seems that I fell prey to the suggestive name of the "following" axis, which
apparently behaves in a different way than I had expected when used in a sorted
<for-each> enumeration: My assumptation was that "following" walks the "current
node list", and that this list is in sorted order within a <for-each> repetition.
(see Chapter 10 of the XSLT Rec: "When a template is instantiated by
xsl:apply-templates and xsl:for-each, the current node list list consists of the
complete list of nodes being processed in sorted order.")

Anyway, the following example proves this assumption wrong (slightly modified from
the "su" example in XT):

Given the following XML:

----------------------------
<doc>
<list>
<item>D</item>
<item>D</item>
<item>A</item>
</list>
<list>
<item>A</item>
<item>B</item>
<item>A</item>
<item>A</item>
<item>C</item>
</list>
<list>
<item>C</item>
<item>A</item>
<item>A</item>
<item>E</item>
</list>
</doc>
----------------------------

and the following XSL:

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

<xsl:output method="text"/>

<xsl:template match="list">
 <xsl:text>(</xsl:text>
 <xsl:for-each select="item[not(. = following::item)]">
   <xsl:sort/>
   <xsl:value-of select="."/>
 </xsl:for-each>
 <xsl:text>)</xsl:text>
</xsl:template>

</xsl:stylesheet>
----------------------------

I get the following output:

----------------------------
(D)
(B)
(ACE)
----------------------------

rather than the expected

----------------------------
(AD)
(ABC)
(ACE)
----------------------------

which I readily get from modifying the "su" sample appropriately. Modifying the
for-each line to

    <xsl:for-each select="item[not(. = following::item[1])]">

gives:

----------------------------
(D)
(AAB)
(ACE)
----------------------------

This seems to indicate two problems with this solution to me:

 - Because of the way the "=" operator is defined in XPath, the comparison works
in a non-intuitve way when comparing the value of the current node against the
*node list* returned by following::item. Explicitly selecting only the immediate
successor using the "[1]" filter kind of fixes this.

 - Inside a <for-each> element, the following:: axis doesn't operate on the sorted
current node list, but rather starts from the original place of the element in the
source tree and continues in document order. The "A" item in the first group of
the sample file is suppressed because it is immediately followed by another "A"
item in the next group.

At least from my point of view, this brings up the question: is there an easy way
to "save" this type of solution by making proper use of the sorted current node
list, or is there really no alternative to either using processor-specific
extensions or setting up more complex recursion schemes? To me, it seems that
having an axis to directly access the current node list would allow for fairly
elegant solution of various sorting'n'grouping problems.

Or am I way off base here?

ciao marcus

ps: And a belated Merry Christmas and a Happy New Year to everyone on the
list... :-)




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


Current Thread