Link to home
Start Free TrialLog in
Avatar of cmain
cmain

asked on

xslt + NaN

Hi,

I am trying to sum up a value using a published algorithm. The algoritm seems to get the correct value, but I cannot seem to format the value without getting NaN. Could anyone help.

Here is the XML.

<client name='Joe Bloggs'>

    <supplier name='A'>
        <product name='C'>
            <investment name='D='1200' price='5.50'/>
            <investment name='E' units='1200' price='3.50'/>
            <investment name='F' units='1345' price='6.55'/>
        </product>
    </supplier>

    <supplier name='B'>
        <product name='E'>
            <investment name='T' units='1200' price='5.50'/>
            <investment name='W' units='1200' price='3.50'/>
            <investment name='S' units='1345' price='6.55'/>
        </product>
    </supplier>

</client>

And here is the xslt.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:palantir="http://www.palantir.co.za"
    version="1.0">
   
<xsl:output
  method = "xml"
  version = "1.0"
  encoding = "UTF-8"
  indent = "yes"/>  
 
  <msxsl:script language="VBScript" implements-prefix="palantir">
  <![CDATA[
 
    Function Format(value)
         
         Format = value
         'Format = FormatCurrency(value)
         
    End Function
   
  ]]>
  </msxsl:script>  
 
  <xsl:template match="/">
  <table>
  <xsl:apply-templates/>
  </table>
  </xsl:template>
 
  <xsl:template match='client'>
  <tr>
    <td><xsl:value-of select='@name'/></td>
    <td>
   
        <xsl:call-template name='total-investment'>
            <xsl:with-param name='investment-set' select='//investment'/>
        </xsl:call-template>
   
    </td>
  </tr>
  </xsl:template>
 
  <xsl:template name='total-investment'>
    <xsl:param name='investment-set'/>
    <xsl:choose>
        <xsl:when test='$investment-set'>
            <xsl:variable name='first-node'>
                <xsl:apply-templates select='$investment-set[1]' mode='investment-price'/>
            </xsl:variable>
            <xsl:variable name='other-nodes'>
                <xsl:call-template name='total-investment'>
                    <xsl:with-param name='investment-set' select='$investment-set[position()!=1]'/>
                </xsl:call-template>
            </xsl:variable>
            <xsl:value-of select='palantir:Format(number(number($first-node) + number($other-nodes)))'/>
        </xsl:when>
        <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
  </xsl:template>                                    
                                   
  <xsl:template match='investment' mode='investment-price'>
    <xsl:value-of select='@units * @price'/>
  </xsl:template>
 
</xsl:stylesheet>

The above xslt works, except when I comment back in the format code it doesn't work.
I have tried the xslt built in functions, and I am getting the same result.

Please help.
Regards
-craig.
Avatar of b1xml2
b1xml2
Flag of Australia image


MODIFIED XSLT DOCUMENT
======================
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method = "xml" version = "1.0" encoding = "UTF-8" indent = "yes"/>  
 
<xsl:template match="/">
<table>
<xsl:apply-templates/>
</table>
</xsl:template>
 
<xsl:template match='client'>
<xsl:variable name="sum">
     <xsl:call-template name='total-investment'>
     <xsl:with-param name='investment-set' select='//investment'/>
     </xsl:call-template>
</xsl:variable>
<tr>
     <td><xsl:value-of select='@name'/></td>
     <td><xsl:value-of select="format-number($sum,'#,###,##0.00')" /></td>
</tr>
</xsl:template>
 
<xsl:template name='total-investment'>
<xsl:param name='investment-set'/>
<xsl:choose>
<xsl:when test='$investment-set'>
<xsl:variable name='first-node'>
<xsl:apply-templates select='$investment-set[1]' mode='investment-price'/>
</xsl:variable>
<xsl:variable name='other-nodes'>
<xsl:call-template name='total-investment'>
<xsl:with-param name='investment-set' select='$investment-set[position()!=1]'/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="number($first-node) + number($other-nodes)"/>
</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>                                    
                                   
 <xsl:template match='investment' mode='investment-price'>
   <xsl:value-of select='@units * @price'/>
 </xsl:template>
 
</xsl:stylesheet>

XML Output
==========
<?xml version="1.0" encoding="UTF-8"?>
<table>
<tr>
<td>Joe Bloggs</td>
<td>39,219.50</td>
</tr>
</table>
The following is a more succinct and better performing stylesheet

Recommended XSLT Document
===========================
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>  

<xsl:template match="/">
<table><xsl:apply-templates/></table>
</xsl:template>

<xsl:template match="client">
<xsl:variable name="total-list">
<xsl:for-each select="descendant::investment">
<sum><xsl:value-of select="@units * @price" /></sum>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="sum" select="sum(msxsl:node-set($total-list)/node())" />
<tr>
<td><xsl:value-of select="@name"/></td>
<td><xsl:value-of select="format-number($sum,'#,###,##0.00')" /></td>
</tr>
</xsl:template>

</xsl:stylesheet>
ASKER CERTIFIED SOLUTION
Avatar of b1xml2
b1xml2
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of cmain
cmain

ASKER

Thanks very much.
I have used a hybrid of your last suggestion as I wish to use parameters and sum at several different levels.

I am still a tad unsure of why I was getting the NaN value, although I will look at it in more detail. Your solution works perfectly, thanks.

Regards
-craig.