Re: [xsl] How to sort by elements of a function output?

Subject: Re: [xsl] How to sort by elements of a function output?
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Fri, 24 Apr 2009 12:17:47 -0400
At 2009-04-24 18:04 +0200, Leo Studer wrote:
I am using Saxon-SA9.1.0.6 to transform the following XML file:
...
with the stylesheet
...
    <xsl:function name="my:MakeTableRow">
        <xsl:param name="team"/>
        <xsl:param name="matches"/>
        <tr>
...
        </tr>
    </xsl:function>
...
            <xsl:for-each-group select="/results/match" group- by="team">
                <xsl:variable name="tableRow"
select="my:MakeTableRow(current-grouping-key(),current-group())"/>
                <xsl:copy-of select="$tableRow"/>
            </xsl:for-each-group>

Note you could have just said the following without creating the variable, though I suppose some processors would optimize that out:


<xsl:copy-of select="my:MakeTableRow(current-grouping-key(),current-group())"/>

In the tag <xsl:for-each-group select="/results/match" group-by="team">
I would like to sort the outcome by the $tableRow/td[8] contents (i.e.
the points) .
How do I do that?

In one pass you would need to recalculate the 8th column for each entry in the group.


The approach

<xsl:for-each-group select="/results/match" group-by="team">
<xsl:sort select="my:MakeTableRow(current-grouping- key(),current-group())/td[8]"
order="descending"/>
<xsl:copy-of select="my:MakeTableRow(current-grouping- key(),current-group())"/>
</xsl:for-each-group>

Interesting ... with just a quick review, I suppose you are doing that recalculation since you are returning the row and indexing off of the 8th column, so I am unsure why the above does not work for you.


Any suggestions?

Create the rows and then sort them:


  <xsl:variable name="rows" as="element(tr)+">
    <xsl:for-each-group select="/results/match" group-by="team">
      <xsl:copy-of
   select="my:MakeTableRow(current-grouping- key(),current-group())"/>
    </xsl:for-each-group>
  </xsl:variable>
  <xsl:for-each select="$rows">
     <xsl:sort select="td[8]"/>
     <xsl:copy-of select="."/>
  </xsl:for-each>

That way you aren't doing the complicated row building twice, only once, and the second pass is a simple copy of nodes.

I think you might find that better than trying to find out why rebuilding the row for the sort criteria isn't working for you.

I hope this helps.

. . . . . . . . . Ken

p.s. just before hitting "send" I see David has quickly determined it was a namespace problem, so the above would be modified along the lines of:

  <xsl:variable name="rows" as="element(xhtml:tr)+">
    <xsl:for-each-group select="/results/match" group-by="team">
      <xsl:copy-of
   select="my:MakeTableRow(current-grouping- key(),current-group())"/>
    </xsl:for-each-group>
  </xsl:variable>
  <xsl:for-each select="$rows">
     <xsl:sort select="xhtml:td[8]"/>
     <xsl:copy-of select="."/>
  </xsl:for-each>


-- XSLT/XSL-FO/XQuery hands-on training - Los Angeles, USA 2009-06-08 Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video Video lesson: http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18 Video overview: http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18 G. Ken Holman mailto:gkholman@xxxxxxxxxxxxxxxxxxxx Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/ Male Cancer Awareness Nov'07 http://www.CraneSoftwrights.com/s/bc Legal business disclaimers: http://www.CraneSoftwrights.com/legal

Current Thread