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 |