Subject:Summarizing chiled nodes problem Author:Ori Tsarfati Date:04 Jan 2005 03:09 AM
this is my XML structure:
..
<o OrderID="10643">
<od ProductID="28" UnitPrice="45.6000" Quantity="15"/>
<od ProductID="39" UnitPrice="18.0000" Quantity="21"/>
<od ProductID="46" UnitPrice="12.0000" Quantity="2"/>
</o>
<o OrderID="10692">
<od ProductID="63" UnitPrice="43.9000" Quantity="20"/>
<od ProductID="50" UnitPrice="12.0000" Quantity="6"/>
</o>
..
this is my XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<table border="1" bgcolor="red">
<xsl:for-each select="//o">
<tr>
<td>
Order ID =
<xsl:value-of select="@OrderID"/>
</td>
<td>
total Quantity =
<xsl:value-of select="sum(child::node()/@Quantity)"/>
</td>
<td>
total order value =
<xsl:value-of select="sum(child::node()/@Quantity*child::node()/@UnitPrice)"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
the result is:
<table>
<tr>
<td>Order ID = 10643</td>
<td>total Quantity = 38</td> - right result (15+21+2)=38
<td>total order value = 684</td> - wrong result! should be ((45.6*15)+(18*21)+(12*2))=(684+378+24)=1086
</tr>
<tr>
<td>Order ID = 10692</td>
<td>total Quantity = 26</td> - right result
<td>total order value = 878</td> - wrong result!
</tr>
</table>
the problem is that the "sum(child::node()/@Quantity)" on a single node works fine, but
the "sum(child::node()/@Quantity*child::node()/@UnitPrice)" gives only the multiply result of the first node and doesn't summarize the other nodes!
any idea way?
10x in adv.
Ori
Subject:Summarizing chiled nodes problem Author:Ori Tsarfati Date:06 Jan 2005 04:30 AM
it looks like we r missing the point, i don't belive that "sum(@xxx*@yyy)" is imposible!
writing this tamplate instead, is the last step, i'm sure that there is a simple way.
any way 10x for the efforts.
Ori.
Subject:Summarizing chiled nodes problem Author:Ori Tsarfati Date:06 Jan 2005 05:44 AM
Well there is an elegant solution to this problem and it looks like this:
first of all u should add a namespace to the stylesheet header:
xmlns:exsl="urn:schemas-microsoft-com:xslt"
extension-element-prefixes="exsl"
then u can use this part:
<xsl:variable name="subTotals">
<xsl:for-each select="//od[../@OrderID=current()/@OrderID]">
<number>
<xsl:value-of select="@Quantity* @UnitPrice"/>
</number>
</xsl:for-each>
</xsl:variable>
<!-- Sum subtotals stored as a result tree fragment in the variable -->
<xsl:value-of select="sum(exsl:node-set($subTotals)/number)"/>
the right xsl will be:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:exsl="urn:schemas-microsoft-com:xslt"
extension-element-prefixes="exsl">
<xsl:template match="/">
<table border="1" bgcolor="red">
<xsl:for-each select="//o">
<tr>
<td>
Order ID =
<xsl:value-of select="@OrderID"/>
</td>
<td>
total Quantity =
<xsl:value-of select="sum(child::node()/@Quantity)"/>
</td>
<td>
total order value =
<xsl:variable name="subTotals">
<xsl:for-each select="child::node()/@Quantity">
<number>
<xsl:value-of select="@Quantity* @UnitPrice"/>
</number>
</xsl:for-each>
</xsl:variable>
<!-- Sum subtotals stored as a result tree fragment in the variable -->
<xsl:value-of select="sum(exsl:node-set($subTotals)/number)"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Subject:Summarizing chiled nodes problem Author:Ivan Pedruzzi Date:06 Jan 2005 11:00 AM
Hi Ori,
Thank you for the follow up.
I am not sure which meter we are using for elegancy here.
It interesting to note that the solution based on a recursive
template runs without any changes on any XSLT 1.0 implementations,
no extension or processor specific code is required.
Another interesting point: the second solution uses RTF to store
the partial result that could be a performance hit depending on
document size and shape.