I have a xml structure like:
1481 test1 test2
This transformation doesn't require the use of any extension functions and doesn't produce an intermediary tree -- in fact it runs with 0 additional memory and is suitable for streaming, if the XSLT processor recognizes tail-recursion:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:apply-templates select="(*/Price/text())[1]">
<xsl:with-param name="pNodes" select="*/Price/text()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="text()" name="sum">
<xsl:param name="pTotal" select="0"/>
<xsl:param name="pNodes"/>
<xsl:param name="pNode1" select="translate($pNodes[1],'+','')"/>
<xsl:value-of select="substring($pTotal+$pNode1, 1 div not($pNodes[2]))"/>
<xsl:apply-templates select="$pNodes[2][$pNode1]">
<xsl:with-param name="pTotal" select="$pTotal+$pNode1"/>
<xsl:with-param name="pNodes" select="$pNodes[position()>1]"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
When it is applied on the provided XML document:
<root>
<PartsDetail>
<Id>1481</Id>
<Desc>test1</Desc>
<GlobDesc>test2</GlobDesc>
<Price Cur="UAH">+798.27</Price>
</PartsDetail>
<PartsDetail>
<Id>0741</Id>
<Desc>test2</Desc>
<GlobDesc>test2</GlobDesc>
<Price Cur="UAH">+399.14</Price>
</PartsDetail>
</root>
The wanted, correct result is produced:
1187.4099999999998
As I understand I need transform price to "normal view (without + and -)" before a send it to function "sum".
That is more or less correct (you don't want to remove the minus sign, in case the number is negative). Given a well-formed input such as:
XML
<root>
<PartsDetail>
<Id>1481</Id>
<Desc>test1</Desc>
<GlobDesc>test2</GlobDesc>
<Price Cur="UAH">+798.27</Price>
</PartsDetail>
<PartsDetail>
<Id>0741</Id>
<Desc>test2</Desc>
<GlobDesc>test2</GlobDesc>
<Price Cur="UAH">+399.14</Price>
</PartsDetail>
</root>
the following stylesheet:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
<xsl:variable name="corrected-prices">
<xsl:for-each select="PartsDetail">
<price>
<xsl:value-of select="translate(Price, '+', '')"/>
</price>
</xsl:for-each>
</xsl:variable>
<sum>
<xsl:value-of select="sum(exsl:node-set($corrected-prices)/price)"/>
</sum>
</xsl:template>
</xsl:stylesheet>
will return:
<?xml version="1.0" encoding="UTF-8"?>
<sum>1197.41</sum>