Reputation: 21
I used recursive function to calculate the total of calculated column (price * quantity), for each invoice and each client. Now I need to calculate the total for all invoices per client and for all invoices for all clients.
xml looks like this:
<cinvoices>
<client> (with information @ client) </client>
<invoices>
<products>
<product> (information @ product: name, type ect and..
<price>123</price>
<quantity>21</quantity>
</product>
<product> (information @ product: name, type ect and..
<price>123</price>
<quantity>11</quantity>
</product>
</products>
<invoices>
<products>
<product> (information @ product: name, type ect and..
<price>32</price>
<quantity>3</quantity>
</product>
<product> (information @ product: name, type ect and..
<price>12</price>
<quantity>9</quantity>
</product>
</products>
</invoices>
</client>
<client>
<same as above>
</client>
</cinvoices>
The function used in xslt is:
<xsl:template name="sumProducts">
<xsl:param name="pList"/>
<xsl:param name="pRunningTotal" select="0"/>
<xsl:choose>
<xsl:when test="$pList">
<xsl:variable name="varMapPath" select="$pList[1]"/>
<xsl:call-template name="sumProducts">
<xsl:with-param name="pList" select="$pList[position() > 1]"/>
<xsl:with-param name="pRunningTotal"
select="$pRunningTotal + $varMapPath/price * $varMapPath/quantity"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
$<xsl:value-of select="format-number($pRunningTotal, '#,##0.00')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
===================== function called as follow:
<xsl:call-template name="sumProducts">
<xsl:with-param name="pList" select="*/*"/>
</xsl:call-template>
Any idea how to use this function to calculate the total for invoices for each client and the grand total for all clients and all invoices.
thank you.
Upvotes: 0
Views: 1655
Reputation: 7662
Let me first rephrase your requirements.
The following template:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template name="sumProducts">
<xsl:param name="pList"/>
<xsl:param name="pRunningTotal" select="0"/>
<xsl:choose>
<xsl:when test="$pList">
<xsl:variable name="varMapPath" select="$pList[1]"/>
<xsl:call-template name="sumProducts">
<xsl:with-param name="pList" select="$pList[position() > 1]"/>
<xsl:with-param name="pRunningTotal" select="$pRunningTotal + $varMapPath/price * $varMapPath/quantity"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
$<xsl:value-of select="format-number($pRunningTotal, '#,##0.00')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/cinvoices/client/invoices">
<xsl:call-template name="sumProducts">
<xsl:with-param name="pList" select="*/*"/>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
applied to the following XML file:
<cinvoices>
<client>
<invoices>
<products>
<product>
<price>123</price>
<quantity>21</quantity>
</product>
<product>
<price>123</price>
<quantity>11</quantity>
</product>
</products>
</invoices>
<invoices>
<products>
<product>
<price>32</price>
<quantity>3</quantity>
</product>
<product>
<price>12</price>
<quantity>9</quantity>
</product>
</products>
</invoices>
</client>
<client>
<invoices>
<products>
<product>
<price>100</price>
<quantity>2</quantity>
</product>
<product>
<price>10</price>
<quantity>1</quantity>
</product>
</products>
</invoices>
</client>
</cinvoices>
should produce the following output:
<?xml version="1.0" encoding="UTF-8"?>
$3,936.00
$204.00
$210.00
So these are values per invoice.
Your solution uses XSLT named template. This problem may solved using different techniques, but I will stick to the idea you already have.
Now, modify the last template with the following code:
<xsl:template match="/cinvoices/client">
<xsl:call-template name="sumProducts">
<xsl:with-param name="pList" select="*/*/*"/>
</xsl:call-template>
</xsl:template>
You will get:
<?xml version="1.0" encoding="UTF-8"?>
$4,140.00
$210.00
These are the totals for all the invoices per client.
Now, modify the last template with this code:
<xsl:template match="/cinvoices">
<xsl:call-template name="sumProducts">
<xsl:with-param name="pList" select="*/*/*/*"/>
</xsl:call-template>
</xsl:template>
And you will get the total for all clients:
<?xml version="1.0" encoding="UTF-8"?>
$4,350.00
Upvotes: 2