Reputation: 99
From the xml below, I want to take the values in each DESC element, extract only the value before INV and add them all up and print the total to a new element called "Total". In other words, if an element contains:
<DESC>TEST SUPPLIER 1 250600FOO 805415446355485 000000002000.00INV 1234</DESC>
Then I only want to extract:
000000002000.00
and do this for all DESC elements, add them together and output it to an element called Total. The DESC element can appear n number of times. Below is an xml with three occurrences:
<?xml version="1.0" encoding="iso-8859-1"?>
<root>
<FOO>OW00007838</FOO>
<BAR>1</BAR>
<DESC>TEST SUPPLIER 1 250600FOO 805415446355485 000000002000.00INV 1234</DESC>
<FOO>OW00007838</FOO>
<BAR>2</BAR>
<DESC>TEST SUPPLIER 2 050712ACME 000256886355485 000000023020.35INV 65870</DESC>
<FOO>OW00007838</FOO>
<BAR>4</BAR>
<DESC>TEST SUPPLIER 3 050712ABCD 000000698745987 000000049158.68INV 02155</DESC>
</root>
And here is my unfinished stylesheet - I'm using substring to attempt to extract the value, but not sure if it's effective. Was thinking of using a combination of substring-before and -after instead:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:exsl="http://exslt.org/common">
<xsl:output indent="yes"/>
<xsl:template match="/">
<Total>
<xsl:variable name="subTotals">
<xsl:for-each select="/root/DESC">
<number>
<xsl:value-of select="substring(.,86,16)"/>
</number>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="sum(exsl:node-set($subTotals)/number)"/>
</Total>
</xsl:template>
Currently the output only returns 0.
Upvotes: 2
Views: 436
Reputation: 1278
Try this,
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
<Total>
<xsl:value-of select="
sum(/root/DESC/number(tokenize(substring-before(., 'INV'),' ')[last()]))"/>
</Total>
</xsl:template>
</xsl:stylesheet>
Result:
<Total>74179.03</Total>
Upvotes: 1
Reputation: 56853
In XSLT you can simply do this:
<xsl:template match="/">
<Total><xsl:value of select="sum(/root/DESC/number(substring(., 86,16)))</Total>
</xsl:template>
The key is wrapping the substring in number()
to make sure it is converted to a number. This may help in your above XSLT 1.0 version as well, I'm not sure.
Also, your data doesn't look valid. In the first DESC to number starts at 76, whereas the last it starts at 87.
Upvotes: 0