Using XSLT 1.0 to summarize a node-set with comma separated values
Pure XSLT is very powerful but it definitely has its weaknesses (I’ve written about how to extend XSLT using mapping and BizTalk previously here) … One of those are handling numbers that uses a different decimal-separator than a point (“.”).
Take for example the XML below
<Prices> <Price>10,1</Price> <Price>10,2</Price> <Price>10,3</Price> </Prices>
Just using the XSLT sum-function on these values will give us a “NaN” values. To solve it we’ll have to use recursion and something like in the sample below.
The sample will select the node-set to summarize and send it to the “SummarizePrice” template. It will then add the value for the first Price tag of the by transforming the comma to a point. It will then check if it’s the last value and if not use recursion to call into itself again with the next value. It will keep adding to the total amount until it reaches the last value of the node set.
<xsl:template match="Prices">
<xsl:call-template name="SummurizePrice">
<xsl:with-param name="nodes" select="Price" />
</xsl:call-template>
</xsl:template>
<xsl:template name="SummurizePrice">
<xsl:param name="index" select="1" />
<xsl:param name="nodes" />
<xsl:param name="totalPrice" select="0" />
<xsl:variable name="currentPrice" select="translate($nodes[$index], ',', '.')"/>
<xsl:choose>
<xsl:when test="$index=count($nodes)">
<xsl:value-of select="$totalPrice + $currentPrice"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="SummurizePrice">
<xsl:with-param name="index" select="$index + 1" />
<xsl:with-param name="totalPrice" select="$totalPrice + $currentPrice" />
<xsl:with-param name="nodes" select="$nodes" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Simple but a bit messy and nice to have for future cut and paste
There's 5 Comments So Far
July 13th, 2010 at 5:59 pm
This works with XSLT 2.0 too. You only need to apply a type conversion for currentPrice: replace row 12 with this one:
July 13th, 2010 at 6:01 pm
LOL… sorry, the code was cutted out:
select=”number(translate($nodes[$index], ‘,’, ‘.’))”
October 15th, 2010 at 9:59 am
How about building a new nodeset?
Something like:
and then sum($pricelistwithdot) ?
October 15th, 2010 at 10:01 am
Tags were stripped in my previous post :S. Maybe they are still available but just not shown?
December 7th, 2011 at 1:47 pm
Thanks! Exactly what I needed.
/ TN
Share your thoughts, leave a comment!