[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

RE: [xsl] A more concise way to handle empty numeric elements


Subject: RE: [xsl] A more concise way to handle empty numeric elements
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Thu, 7 Jun 2007 14:24:34 +0100

Google for "XSLT 1.0 sum of computed value"

(You're wanting to compute the numbers being summed by replacing "" by 0).

Not easy in XSLT 1.0, but there are a number of solutions. Much easier in
2.0.

Michael Kay
http://www.saxonica.com/

> -----Original Message-----
> From: Mark Anderson [mailto:mark.anderson@xxxxxxxxxxxxxxxxxxx]
> Sent: 07 June 2007 14:01
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] A more concise way to handle empty numeric elements
>
> Hi All
>
> I have to process an XML file that contains a lot of numeric
> data. Many of the elements that have no value are empty
> instead of being zero and it may differ for each line, for example
>
> <line id=1>
>             <cost1>1000</cost1>
>             <cost2>0</cost2> <!-- 0 here, but empty in next line -->
>             <cost3></cost3>
> </line>
> <line id=2>
>             <cost1>2000</cost1>
>             <cost2></cost2>
>             <cost3>3000</cost3>
> </line>
>
> I want to do:
>
> <xsl:for-each select="line">
>        <xsl:value-of select="format-number(cost1 + cost2 +
> cost3,'#,###')"/>
>       </xsl:for-each>
>
> However, the empty elements will cause "NaN" to be displayed
>
> To fix it I can do:
>
> <xsl:for-each select="line">
> <xsl:variable name="cost1">
>       <xsl:choose>
>             <xsl:when test="(cost1 &gt;= 0)"><xsl:value-of
> select="cost1"/></xsl:when>
>             <xsl:otherwise>0</xsl:otherwise>
>       </xsl:choose>
> </xsl:variable>
> <xsl:variable name="cost2">
>       <xsl:choose>
>             <xsl:when test="(cost2 &gt;= 0)"><xsl:value-of
> select="cost2"/></xsl:when>
>             <xsl:otherwise>0</xsl:otherwise>
>       </xsl:choose>
> </xsl:variable>
> <xsl:variable name="cost3">
>       <xsl:choose>
>             <xsl:when test="(cost3 &gt;= 0)"><xsl:value-of
> select="cost3"/></xsl:when>
>             <xsl:otherwise>0</xsl:otherwise>
>       </xsl:choose>
> </xsl:variable>
>        <xsl:value-of select="format-number($cost1 + $cost2 +
> $cost3,'#,###')"/>
>       </xsl:for-each>
>
> However, it seems very long winded. Also the output is HTML,
> so it makes it hard to read the HTML with so much XML interwoven.
>
> I realized I could write a template to return 0 for each
> empty element, but the call-template and parameter
> declaration will add further lines.
>
> Is there a more succinct/elegant way to do it? (it's a shame
> "number(cost1)" doesn't return 0 for empty elements)
>
> BTW: I'm using XSLT1.0 and can't use any extensions
>
> Thanks in advance
> M a r k 


Current Thread
Keywords