'XSL How to calculate the sum of a specific tag [duplicate]
I work in a furniture factory, and the software we use generates a big xml file with data of an entire project (multiple ambients of 1 house) with all its furnitures and accessories. Below I copied only part of the file, specifically the path to the "references" folder, which contains the variable "UPE" I want to sum. (the last one)
<?xml version="1.0" encoding="utf-8"?>
<LISTING
<AMBIENTS>
<AMBIENT> `Here there are multiple ambients`
<CATEGORIES>
<CATEGORY>
<ITEMS> `Here there are multiple items`
<ITEM>
<REFERENCES>
<CODE REFERENCE="ZCBC2CS60ML" />
<CHECKINT REFERENCE="" />
<CODIGO_TEXTURA REFERENCE="ML" />
<CHECKNAME REFERENCE="Cierre Suave" />
<CODE_MATERIAL REFERENCE="MBCO18" />
<NAME_MATERIAL REFERENCE="Mel. Blanca" />
<TIPOPUERTA REFERENCE="VIVER" />
<COMPLETE REFERENCE="ZCBC2CS60ML" />
<LINEA REFERENCE="ZC" />
<MODEL REFERENCE="Viver - Mel. Blanca" />
<MODULO REFERENCE="BC" />
<ANCH REFERENCE="60" />
<PROP REFERENCE="2C" />
<INTCAJ REFERENCE="S" />
<CHECK REFERENCE="CS" />
<CHECK_CHARM REFERENCE="" />
<REF_PYF_MYT REFERENCE="Viver - Mel. Blanca" />
<REF_FRENTE REFERENCE="Viver" />
<DETALLE_LAYOUT REFERENCE="Viver - Mel. Blanca" />
<DESCRIPCION REFERENCE="BC2C60" />
**<UPE REFERENCE="11,5" />**
This variable contains always a decimal number. I want to calculate the sum of "UPE" in the entire big file. I have tried:
<xsl:for-each select="/LISTING/AMBIENTS/AMBIENT">
<xsl:value-of select="sum(CATEGORIES/CATEGORY/ITEMS/ITEM/REFERENCES/@UPE)"/>
</xsl:for-each>
but it didn't work and then I read that "sum" only works in xml 2.0, so I found a "for-each loop" example from this page but I haven't got that to work either:
<xsl:for-each select="/LISTING/AMBIENTS/AMBIENT">
<xsl:call-template name="PercorrerUPE">
<xsl:with-param name="tempSum" select="0"/>
<xsl:with-param name="nivel" select="0"/>
</xsl:call-template>
</xsl:for-each>
<xsl:template name="PercorrerUPE">
<xsl:param name="nivel"/>
<xsl:param name="tempSum"/>
<xsl:if test="count(ITEMS) > 0" >
<xsl:for-each select="CATEGORIES/CATEGORY/ITEMS/ITEM/REFERENCES">
<xsl:call-template name="sumUPE">
<xsl:with-param name="nivel" select="$nivel"/>
<xsl:with-param name="tempSum" select="$tempSum"/>
</xsl:call-template>
</xsl:for-each>
</xsl:if>
</xsl:template>
<xsl:template name="sumUPE">
<xsl:param name="nivel" />
<xsl:param name="tempSum" />
<xsl:if test="count(ITEMS) > 0" >
<xsl:variable name="UPE" select="@UPE"/>
<xsl:call-template name="PercorrerUPE">
<xsl:with-param name="tempSum" select="($tempSum + UPE)"/>
<xsl:with-param name="nivel" select="$nivel + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
What am I doing wrong or have I missed something?
Solution 1:[1]
Your number is written with comma as a decimal separator, and this makes things awkward because (a) the built-in string-to-number conversion in XPath only recognises "." as decimal separator, and (b) XPath 1.0 has no mechanism to sum over a set of computed numbers (as distinct from numbers directly present in the source).
(Your statement "I read that "sum" only works in xml 2.0" means that you're reading in the wrong places. There is no xml 2.0, and if they meant XPath rather than xml, then sum() does work in XPath 1.0, but only over a set of nodes that directly contain the numbers. You need to find more reliable sources of information about the tools you are using...)
For XSLT 1.0, it looks like you've found some code that solved this problem using recursion, and you've copied-and-pasted the code without understanding how it was supposed to work. (Not a good programming technique...). You've made a lot of mistakes in the transcription, for example using UPE as an attribute and a variable and an element.
Is there any reason you're stuck with XSLT 1.0? This would be so much easier if you upgraded.
If you really are constrained to 1.0
You've missed the key point that before doing arithmetic on UPE you need to convert it to something that XPath regards as a number:
$tempSum + UPE
should be
$tempSum + translate(UPE, ',', '.')
I'm not going to code it for you, partly because I haven't written XSLT 1.0 code for nearly 20 years, and partly because I think you shouldn't be using the recursion technique unless you actually understand it.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Michael Kay |
