p2p.wrox.com Forums

Need to download code?

View our list of code downloads.

  Return to Index  

xslt thread: getting preceding-sibling with sorted results

Message #1 by "Nate Baxley" <baxley@c...> on Wed, 19 Jun 2002 21:51:47
You're using one particular way of doing grouping. It's a legitimate
approach, though not one of the standard techniques. But if you want to
do it this way, you have to copy the sorted data into a temporary tree,
and access the temporary tree using the xx:node-set() extension
function, because the preceding-sibling axis, as you noted, uses the
relationships in the source tree you are processing, not the transient
sequence established by the sort.

I would recommend using a different grouping approach, using nested
loops instead of sorting. There are two standard methods, the
preceding-sibling method and the Muenchian method. Both rely on an outer
loop selecting a representative element of each group, and an inner loop
(or perhaps just an aggregation function such as sum() or count())
accessing all the members of each group in turn.

With the preceding-sibling technique this is:

<xsl:for-each select="X[not(@a=preceding-sibling::X/@a]">
    <xsl:for-each select="../X[@a=current()/@a]">

Muenchian grouping uses xsl:key - it is faster and more general, but
harder to code. For details look up Muenchian grouping in XSLT
Programmer's Reference, or see

Alternatively, it all becomes much easier in XSLT 2.0 with
<xsl:for-each-group>: you can try this with Saxon 7.1.

Michael Kay
Software AG
home: Michael.H.Kay@n...
work: Michael.Kay@s... 

> -----Original Message-----
> From: Nate Baxley [mailto:baxley@c...] 
> Sent: 19 June 2002 21:52
> To: P2P_XSLT
> Subject: [xslt] getting preceding-sibling with sorted results
> I need to get subtotals on a set of data two different ways.  
> I'll simplify it a little for the sake of clarity.  I need to 
> get subtotals based on attribute A and a different set of 
> subtotals based on B.  I can generate the XML ordered by A 
> and then use the preceding-sibling technique to build a uniqe 
> list of subtotals.  But when I try sorting the tree before 
> using preceding-sibling it appears to get the preceding 
> sibling based on the order in the original tree.  I'm 
> attaching some snippets to show the problem.  Can anyone see 
> a way around this problem?
> Thanks in advance,
> Nate Baxley
> <xsl:apply-templates select="Action">
>    <xsl:sort select="@B" />
> </xsl:apply-templates>
> <xsl:template match="Action">
>    <xsl:if test="./preceding-sibling::Action[1]/@B != ./@B or 
> position() = last()">
>       <tr>
>          <td><xsl:value-of 
> select="./preceding-sibling::Action[1]/@B"/></td>
>          <td align="right">
>             <xsl:variable 
>                name="B" 
>                select="./preceding-sibling::Action[1]/@B" />
>             <xsl:value-of 
> select="sum(../Action[@B=$B]/@SalesAmount)"/>
>          </td>
>       </tr>
>    </xsl:if>
> </xsl:template>

  Return to Index