Reputation: 163
I want to Round values if more than two digits in XSLT.
Input
<table>
<tr>
<td>3.310</td>
<td>3.245</td>
<td>3.882</td>
<td>1.091</td>
</tr>
</table>
The output should be:
<ans>
<rt>6.5</rt
</ans>
Tried code:
<xsl:template match="table/tr">
<xsl:variable name="change" select="td[1]-td[2]"/>
<xsl:variable name="xxx" select="format-number($change * 100,'0.0')"/>
<xsl:choose>
<xsl:when test="$change mod 1 eq 0">
<xsl:value-of select="format-number($xxx,0)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="format-number($xxx,0.0)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Logic:
If there are two decimals, round up to a single decimal. For example:
(3.310 - 3.245) * 100 = 6.5
(0.320 - 0.350) * 100 = 2.95 => rounded up = 3
(0.51 - 0.495) * 100 = 1.5
The error I am getting:
Arithmetic operator is not defined for arguments of types (xs:string, xs:integer)
I am using XSLT 2.0
Upvotes: 1
Views: 368
Reputation: 243599
Logic:
If there are two decimals, round up to a single decimal. For example:
(3.310 - 3.245) * 100 = 6.5
(0.320 - 0.350) * 100 = 2.95 => rounded up = 3
(0.51 - 0.495) * 100 = 1.5
. . . .
I am using XSLT 2.0
Here is one correct solution:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my:my">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="num/text()">
<xsl:value-of select="my:round-two-digits(xs:decimal(.)), '
'"/>
</xsl:template>
<xsl:function name="my:round-two-digits" as="xs:decimal">
<xsl:param name="pNum" as="xs:decimal"/>
<xsl:sequence select=
"if(floor($pNum * 10) eq ($pNum * 10))
then $pNum
else round($pNum)"/>
</xsl:function>
</xsl:stylesheet>
To test this, apply the above transformation on the following XML document:
<nums>
<num>6.5</num>
<num>2.95</num>
<num>1.5</num>
</nums>
The wanted, correct result is produced:
6.5
3
1.5
Note:
I personally prefer to use more compact XPath expressions, so the above can be re-written as:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my:my">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="num/text()">
<xsl:value-of select="my:round-two-digits(xs:decimal(.)), '
'"/>
</xsl:template>
<xsl:function name="my:round-two-digits" as="xs:decimal">
<xsl:param name="pNum" as="xs:decimal"/>
<xsl:sequence select=
"($pNum[floor($pNum * 10) eq ($pNum * 10)],
round($pNum))
[1]"/>
</xsl:function>
</xsl:stylesheet>
Upvotes: 0
Reputation: 58
Please check below code:
<xsl:template match="table/tr">
<xsl:variable name="change" select="td[1]-td[2]"/>
<xsl:variable name="xxx" select="number(format-number($change * 100,'0.0'))"/>
<ans>
<rt>
<xsl:choose>
<xsl:when test="$change mod 1 eq 0">
<xsl:value-of select="round($xxx)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="round($xxx)"/>
</xsl:otherwise>
</xsl:choose>
</rt>
</ans>
</xsl:template>
Upvotes: 2
Reputation: 117165
You are getting the error because you are trying to format a number that is already formatted. The result of formatting a number is a string.
I don't see why you need to format the number twice. Moreover, if you want to round a number, you should be using the round()
function. Formatting a number is not the same thing. For example,
round(0.5)
returns 1, but
format-number(0.5, '0')
returns 0.
Upvotes: 1