Agreed, most of it is easy, up to the grand total part.
For this, there are 2 recommended methods:
1. Recursive template, adding up the product from each part, pass sum as parameter or result
2. Create a temporary variable with the products. Then sum up using the sum function and the node-set function if necessary.
1. Pros: does not require extension functions.
Cons: uses more memory. Can break if there are too many nodes to calculate.
2. Pros: Requires only single pass.
Cons: Requires use of XSLT 2.0, or the node-set extension function, which differs across processors.
quick example of 1:
-
<xsl:template name="addProducts">
-
<xsl:variable name="currentProduct" select="(*/Months) * (*/Amount)"/>
-
<xsl:choose>
-
<xsl:when test="not(following-sibling::*)">
-
<xsl:value-of select="$currentProduct"/>
-
</xsl:when>
-
<xsl:otherwise>
-
<xsl:variable name="$nextProductSums">
-
<xsl:for-each select="following-sibling::*[1]">
-
<xsl:call-template name="addProducts"/>
-
</xsl:for-each>
-
</xsl:variable>
-
<xsl:value-of select="$nextProductSums + $currentProduct"/>
-
</xsl:otherwise>
-
</xsl:choose>
-
</xsl:template>
-
Quick example of 2:
-
<xsl:variable name="products">
-
<xsl:for-each select="*">
-
<node>
-
<xsl:value-of select="(*/Months) * (*/Amount)"/>
-
</node>
-
</xsl:for-each>
-
</xsl:variable>
-
-
<xsl:value-of select="sum($products/node)"/>
-