Re: [xsl] variables in sort statements: (was Grouping and Sortin g on value inside group)

Subject: Re: [xsl] variables in sort statements: (was Grouping and Sortin g on value inside group)
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Wed, 12 Jun 2002 18:57:45 +0100
Hi Tom,

> I think there's something strange going on with variables in sort
> statemenents. I'm trying a simple version of what Peter was doing in
> the previous thread.
>
> The source looks like this:
> <a>
> <b id='1'>b1</b>
> <d id='2'>2</d>
> <b id='3'>b3</b>
> <c id='1'>c1</c>
> <c id='2'>c2</c>
> <c id='3'>c3</c>
> <b id='2'>b2</b>
> <d id='1'>3</d>
> <d id='3'>1</d>
> </a>
>
> and I want to group by @id, and order the grouping by the value of a
> specific child of a, either b,c or d.
>
> This doesn't work:
>         <xsl:variable name='sortcol' select='"d"'/>
>                 <xsl:for-each select='a/*[generate-id() =
> generate-id(key("key",@id))]'>
>                         <xsl:sort select='../*[local-name() = $sortcol][@id
> = current()/@id]'/>
>                                 <x><xsl:value-of select="@id"/></x>
> The @ids come out 1, 2, 3
>
> This does work:
>         <xsl:variable name='sortcol' select='"d"'/>
>                 <xsl:for-each select='a/*[generate-id() =
> generate-id(key("key",@id))]'>
>                         <xsl:sort select='../*[local-name() = "d"][@id =
> current()/@id]'/>
>                                 <x><xsl:value-of select="@id"/></x>
> The @ids come out 3, 2, 1, as desired.

What processor are you using? I tested with Saxon, Xalan, libxslt,
MSXML3 and MSXML4. They all gave consistent results (i.e. both
xsl:for-eaches gave the same sequence), although MSXML4 wrongly gave
1, 2, 3 each time (I think because it doesn't realise that current()
should give the node being sorted).

A better method of doing the sort, perhaps, would be to use the key to
retrieve the elements with the relevant id and then filter those to
get the one that has the name you want:

  <xsl:variable name="sortcol" select="'d'" />
  <xsl:for-each
      select="a/*[generate-id() = generate-id(key('key', @id))]">
    <xsl:sort select="key('key', @id)[local-name() = $sortcol]" />
    <x><xsl:value-of select="@id" /></x>
  </xsl:for-each>

This has the advantage of working with MSXML4, and it should be
faster.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


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


Current Thread