|
Subject: Re: [xsl] xsl:sort by a sum()? From: "Joerg Heinicke" <joerg.heinicke@xxxxxx> Date: Thu, 11 Apr 2002 23:03:49 +0200 |
It's not so difficult. With using current(), which returns the current node,
you can change your sum()-function, so that it works in the <xsl:sort/>.
<xsl:template match="/">
<xsl:for-each select="//Fruit[@name and
not(@name=preceding::Fruit/@name)]">
<xsl:sort select="sum(//Fruit[@name=current()/@name]/@amount)"/>
<xsl:value-of select="@name"/>
<xsl:text> : </xsl:text>
<xsl:value-of select="sum(//Fruit[@name=current()/@name]/@amount)"/>
<br/>
</xsl:for-each>
</xsl:template>
But this makes the code not better. For this 9 lines of code all your XML
nodes have to be accessed at least 3 times, because of '//'. Furthermore you
are using the preceding-axis. So for every <Fruit> all nodes before this
node are accessed again. So a little bit bigger file will increase your
processing times extremely.
The first step for optimization is to replace the '//' by a more explicit
XPATH: '/root/FruitBasket/Fruit' (I added <root> as document element.) So
the processor knows where to find the <Fruit>s.
Then you can change the template structure instead of using <xsl:for-each>:
<xsl:template match="root">
<xsl:apply-templates select="FruitBasket/Fruit[@name and
not(@name=preceding::Fruit/@name)]">
<xsl:sort
select="sum(/root/FruitBasket/Fruit[@name=current()/@name]/@amount)"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Fruit">
<xsl:value-of select="@name"/>
<xsl:text> : </xsl:text>
<xsl:value-of
select="sum(/root/FruitBasket/Fruit[@name=current()/@name]/@amount)"/>
<br/>
</xsl:template>
Then I replace the preceding-axis by the preceding-sibling-axis, so that
only the preceding nodes on the same level are accessed.
select="FruitBasket/Fruit[@name and
not(@name=../preceding-sibling::FruitBasket/Fruit/@name)]"
And now forget this and I show you a complete different method. It's called
Muenchian Method and explained at
http://www.jenitennison.com/xslt/grouping/muenchian.xml.
<!-- building a key-table where the <Fruit>s are 'grouped' by its @name -->
<xsl:key name="Fruits" match="Fruit" use="@name"/>
<xsl:template match="root">
<!-- apply template on the first node of every 'group' -->
<xsl:apply-templates select="FruitBasket/Fruit[count( . | key('Fruits',
@name)[1] ) = 1]">
<!-- key('Fruits', @name) returns all <Fruit>s with this @name -->
<xsl:sort select="sum(key('Fruits', @name)/@amount)"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Fruit">
<xsl:value-of select="@name"/>
<xsl:text> : </xsl:text>
<xsl:value-of select="sum(key('Fruits', @name)/@amount)"/>
<br/>
</xsl:template>
This is really easy code, more readable and really time-saving.
hope this helps,
Joerg
> <FruitBasket location="kitchen">
> <Fruit name="Apples" amount="10"/>
> <Fruit name="Oranges" amount="20"/>
> </FruitBasket>
> <FruitBasket location="bedroom">
> <Fruit name="Apples" amount="8"/>
> <Fruit name="Oranges" amount="7"/>
> </FruitBasket>
>
> And the following <xsl:for-each>:
>
> <xsl:for-each select="//Fruit[@name and
not(@name=preceding::Fruit/@name)]">
> <xsl:variable name="currentFruit" select="@name"/>
> <xsl:value-of select="$currentFruit"><xsl:text> : </xsl:text><xsl:value-of
> select="sum(//Fruit[@name=$currentFruit]/@amount)"/><br/>
> </xsl:for-each>
>
> After processing with Saxon 6.5.1 I get this:
> Apples: 18
> Oranges: 27
>
> Which is fine and dandy, but I've got 25 FruitBaskets with different
amount
> of fruits each, so I need to sort them by the sum of each Fruit among
> FruitBaskets. Is there an Xpath expression that could achieve that? I had
> tried many, and also searched in the list, but I couldn't find something
> similar to my case.
>
> Many thanks in advance for the tip.
>
> Cheers,
>
> Juan
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| [xsl] xsl:sort by a sum()?, Juan Gril | Thread | [xsl] after use of document(): sele, Ralph Holz |
| RE: [xsl] variable in xpath?, Steve Renshaw | Date | RE: [xsl] variable in xpath?, David N Bertoni/Camb |
| Month |