Reputation: 55
I've been having issues while doing arithmetic operations on following XML
Source XML
<?xml version="1.0" encoding="UTF-8"?>
<Compensation>
<Salary>
<BasePay>$18600.12</BasePay>
<Bonus>$3500.99</Bonus>
<Gym>$670</Gym>
<Tax>$30,000</Tax>
</Salary>
<Salary>
<BasePay>$28600.12</BasePay>
<Bonus>$1500.99</Bonus>
<Gym/>
<Tax>$50,000</Tax>
</Salary>
</Compensation>
Current XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:this="urn:this-stylesheet"
exclude-result-prefixes="xs this"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:function name = "this:translateCurrency">
<xsl:param name="stringValue"/>
<xsl:value-of select="format-number(xs:decimal(translate(xs:string($stringValue), '$,','')), '#.##')"/>
</xsl:function>
<xsl:template match="Compensation">
<Worker>
<xsl:for-each select="Salary">
<Comp>
<Amount>
<xsl:value-of select="this:translateCurrency(BasePay) - this:translateCurrency(Tax) "/>
</Amount>
<NoBonus>
<xsl:value-of select="this:translateCurrency(BasePay) + this:translateCurrency(Gym) "/>
</NoBonus>
</Comp>
</xsl:for-each>
</Worker>
</xsl:template>
</xsl:stylesheet>
Currency symbol and commas will always be present in amount related XML elements such as <BasePay>
<Bonus>
<Gym>
<Tax>
which i am translating and converting to decimal before adding or substracting.
There are two issues
1. Since my source XML have many Amount related fields, I have declared a function for translating and converting to decimal. However, I'm unable to get my function rounding to two decimal points. I was expecting following line of code in my function will be able to round to two decimal points.
<xsl:value-of select="format-number(xs:decimal(translate(xs:string($stringValue), '$,','')), '#.##')"/>
2. It's possible that some of the amount fields may be null for e.g. <Gym/>
is null in my Source XML and current version of XSLT returns Cannot convert to string "" to xs:decimal no digits in value.
I tried $stringValue!=''
in xsl:function statement and Gym!=''
but to no avail.
Can anyone help me figure out what i should be doing to get my function round to two decimal points and get past no digits in value
error?
<NoBonus>
<xsl:value-of select="this:translateCurrency(BasePay) + this:translateCurrency(Gym!='') "/>
</NoBonus>
Expected Result
<?xml version="1.0" encoding="UTF-8"?>
<Worker>
<Comp>
<Amount>-11399.88</Amount>
<NoBonus>19270.12</NoBonus>
</Comp>
<Comp>
<Amount>-21399.88</Amount>
<NoBonus>28600.12</NoBonus>
</Comp>
</Worker>
Upvotes: 0
Views: 231
Reputation: 167716
If you want to convert a string to a decimal value then don't use format-number
on it. So for your input values to be converted into xs:decimal
s you need e.g.
<xsl:function name="this:translateCurrency" as="xs:decimal">
<xsl:param name="input" as="xs:string"/>
<xsl:sequence
select="if ($input = '')
then 0
else xs:decimal(translate($input, '$,', ''))"/>
</xsl:function>
Then use those xs:decimal
values in any arithmetic computations, only where you need to output the final result of an arithmetic computation in a certain format use format-number
on that result to ensure e.g. you get two decimals.
Upvotes: 1