How do I sum one attribute while grouping by another?
From examples online (including posts in this list) I'm pretty sure a
recursive template is necessary but I can't figure out how. Unfortunately,
all the examples are too simple (e.g. increment counter with position()) or
assume you can divide the data by elements. All my elements are the same.
For instance, I have the following XML data:
<food>
<item type="fruit" name="apple" rotten="6" total="10"/>
<item type="fruit" name="orange" rotten="2" total="10"/>
<item type="fruit" name="pear" rotten="1" total="4"/>
<item type="vegetable" name="carrot" rotten="0" total="5"/>
<item type="vegetable" name="potato" rotten="1" total="2"/>
</food>
To which I apply a stylesheet to get a nice table output. I know how to get
to overall sums, but I don't know how to get the group/inner sums (denoted
by '?'):
type name rotten total percent
fruit
apple 6 10 60
orange 2 10 20
pear 1 4 25
total ? ? ?
vegetable
carrot 0 5 0
potato 1 2 50
total ? ? ?
total 10 31 32.3
Here are some assumptions that can be made about the data:
* The items are guaranteed to be sorted by the "type" attribute.
* I don't know the possible values of "type" beforehand.
* Its format cannot be changed.
Also:
* I am using XSLT 1.0, but upgrading to 2.0 might be possible (I'm not
sure).
* I am using python 2.4 with libxml2 and libxslt.
Here's the stylesheet I have now (that generated the above table):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html><body><table>
<tr>
<td>type</td>
<td>name</td>
<td>rotten</td>
<td>total</td>
<td>percent</td>
</tr>
<xsl:for-each select="//item">
<xsl:if test="not(preceding-sibling::*[1]/@type=(_at_)type)">
<tr><td><xsl:value-of select="@type"/></td></tr>
</xsl:if>
<tr>
<td></td>
<td><xsl:value-of select="@name"/></td>
<td><xsl:value-of select="@rotten"/></td>
<td><xsl:value-of select="@total"/></td>
<td><xsl:value-of select="format-number(@rotten div @total *
100,'##.#')"/></td>
</tr>
<xsl:if test="not(following-sibling::*[1]/@type=(_at_)type)">
<tr>
<td></td>
<td>total</td>
<td>?</td>
<td>?</td>
<td>?</td>
</tr>
</xsl:if>
</xsl:for-each>
<tr>
<td>total</td>
<td></td>
<td><xsl:value-of select="sum(//item/@rotten)"/></td>
<td><xsl:value-of select="sum(//item/@total)"/></td>
<td><xsl:value-of select="format-number(sum(//item/@rotten) div
sum(//item/@total) * 100,'##.#')"/></td>
</tr>
</table></body></html>
</xsl:template>
</xsl:stylesheet>
Thank you,
DB
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--