Reputation: 1
I have to add two variables with scientific number values in XSLT. I am getting NAN, when I used something like this xsl:with-param name="inputVal" select="($price1+$price2)". where Price1 = 1.0E7 and Price2 = 1.0E8. I have issue with Sum() as well.
Here is an example of what I am looking for My XML :
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd>
<title>CD1</title>
<price>1.0E7</price>
</cd>
<cd>
<title>CD2</title>
<price>1.1E7</price>
</cd>
<cd>
<title>CD3</title>
<price>1.2E7</price>
</cd>
</catalog>
My XSLT :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Price</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td>
<xsl:value-of select="title"/></td>
<td><xsl:call-template name="convertSciToNumString">
<xsl:with-param name="inputVal" select="price"/>
</xsl:call-template></td>
</tr>
</xsl:for-each>
<tr>
<th>Total</th>
<th><xsl:value-of select="sum(catalog/cd/price)"/></th>
</tr>
</table>
</body>
</html>
</xsl:template>
<xsl:template name="convertSciToNumString" >
<xsl:param name="inputVal" select="0"/>
<xsl:variable name="vMantissa" select="substring-before($inputVal, 'E')"/>
<xsl:variable name="vExponent" select="substring-after($inputVal, 'E')"/>
<xsl:variable name="vExponentAbs" select="translate($vExponent, '-', '')"/>
<xsl:variable name="vFactor" select="substring('100000000000000000000000000000000000000000000', 1, substring($vExponentAbs, 1) + 1)"/>
<xsl:choose>
<xsl:when test="$inputVal = ''">
</xsl:when>
<xsl:when test="number($inputVal)=$inputVal">
<xsl:value-of disable-output-escaping="no" select="format-number($inputVal, '##,###,###,###,###,###,##0.00')"/>
</xsl:when>
<xsl:when test="starts-with($vExponent,'-')">
<xsl:value-of disable-output-escaping="no" select="format-number($vMantissa div $vFactor, '##,###,###,###,###,###,##0.00')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of disable-output-escaping="no" select="format-number($vMantissa * $vFactor, '##,###,###,###,###,###,##0.00')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
I am using version 1.0 and by following the suggestion to create a template to convert data from scientific format to number format, I am able to individually, but as I have to use sum() or variable1 + variable2 in some cases, I am not sure how to handle this.
Upvotes: 0
Views: 252
Reputation: 117140
The main problem with your attempt is that your template returns a formatted string, not a number.
The other thing is that you need to do this in two passes: first, convert the scientific-notation values to numbers; then sum the resulting numbers and - if necessary - format them for output.
If you are using the Apache Xalan processor, you can make this much easier by utilizing the EXSLT math:power() extension function:
XSLT 1.0 (+ EXSLT)
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:math="http://exslt.org/math"
extension-element-prefixes="exsl math">
<xsl:template match="/catalog">
<!-- FIRST PASS -->
<xsl:variable name="cds-rtf">
<xsl:for-each select="cd">
<xsl:copy>
<xsl:copy-of select="title"/>
<price>
<xsl:variable name="significand" select="substring-before(price,'E')"/>
<xsl:variable name="magnitude" select="substring-after(price,'E')"/>
<xsl:value-of select="$significand * math:power(10, $magnitude)"/>
</price>
</xsl:copy>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="cds" select="exsl:node-set($cds-rtf)/cd"/>
<!-- OUTPUT -->
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr>
<th>Title</th>
<th>Price</th>
</tr>
<xsl:for-each select="$cds">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="format-number(price, '#,###')"/>
</td>
</tr>
</xsl:for-each>
<tr>
<th>Total</th>
<th>
<xsl:value-of select="format-number(sum($cds/price), '#,###')"/>
</th>
</tr>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Applied to your input example, this will produce:
Result (rendered)
Upvotes: 0