[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: xsl:sort by a sum()?

Subject: Re: xsl:sort by a sum()?
From: "Joerg Heinicke" <joerg.heinicke@xxxxxx>
Date: Thu, 11 Apr 2002 23:03:49 +0200
xsl sort sum
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

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.