RE: [xsl] sorting question

Subject: RE: [xsl] sorting question
From: "Diamond, Jason" <Jason.Diamond@xxxxxxx>
Date: Wed, 7 Mar 2001 17:13:54 -0600
Since it's not possible to sort node-sets when selecting them (with
<xsl:variable>, for example), the positions of the nodes in your $letters
variable are different than the positions of the nodes as you loop over them
(because of the <xsl:sort> element).

So, if you just loop over the sorted nodes and keep track of your position
in that list, you can control when you output the '(' as opposed to the ')'.

The following transform seems to produce the output that you want using both
MSXML3 and SAXON 6.2:

<xsl:transform version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>
  <xsl:output method="text" encoding="UTF-8"/>

  <xsl:template match="ALPHABET">
    <xsl:for-each select="LETTER">
      <xsl:sort select="."/>
      <xsl:choose>
        <xsl:when test="position() mod 2 = 1">
          <xsl:text>(</xsl:text>
          <xsl:value-of select="."/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>,</xsl:text>
          <xsl:value-of select="."/>
          <xsl:text>)</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>

</xsl:transform>

You'll be left with an unclosed pair if you happen to have an odd number of
nodes but you could check for that by testing the count of the LETTER nodes
and outputting a closing a ')' if necessary.

Hope this helps,
Jason.

-----Original Message-----
From: Oliver Rutherfurd [mailto:fruhstuck@xxxxxxxxxxxxxx]
Sent: Wednesday, March 07, 2001 11:35 AM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: [xsl] sorting question


Hello,

I'm trying to transform a list of elements into a sorted set of pairs, and
haven't
been able to determine how to get the 'next' sorted element relative to the
current
position.  As I couldn't get it to work with 'real' data, I simplified it to
make it easier to play with (and explain).  Below is a little xml and the
xsl
I'm trying to use.  Any tips or hints would be great!

here's a little data:

<ALPHABET>
 <LETTER>a</LETTER>
 <LETTER>d</LETTER>
 <LETTER>b</LETTER>
 <LETTER>c</LETTER>
</ALPHABET>

I would like results like:

(a,b)(c,d)

The following selects the second element based on it's position in nodeset,
not the sorted nodeset.

<xsl:variable name="letters" select="/ALPHABET/LETTER" />

<xsl:for-each select="$letters">
 <xsl:sort select="." />
 <xsl:if test="(position() mod 2) = 1">
  <xsl:variable name="next_index" select="number(position() + 1)" />
  <!--[<xsl:value-of select="position()" />,<xsl:value-of
select="$next_index" />]-->
  (<xsl:value-of select="." />,<xsl:value-of select="$letters[$next_index]"
/>)
 </xsl:if>
</xsl:for-each>

I checked out the xsl faq, and I found a posting of
Jeni's that showed how to copy a sorted list into a variable, but
it doesn't seem to be working for me.
(I'm using MSXML3 in case that matters...)

<xsl:variable name="letterlist">
 <xsl:for-each select="/ALPHABET/LETTER">
  <xsl:sort select="." />
  <xsl:copy-of select="." />
 </xsl:for-each>
</xsl:variable>

<!-- nothing comes out... -->
<xsl:value-of select="$letterlist" />

Thanks,
-Ollie Rutherfurd
fruhstuck@xxxxxxxxxxxxxx


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

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


Current Thread