Solved

xslt + NaN

Posted on 2002-03-25
4
6,962 Views
Last Modified: 2013-11-18
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.
0
Comment
Question by:cmain
  • 3
4 Comments
 
LVL 23

Expert Comment

by:b1xml2
ID: 6895283

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>
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6895652
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>
0
 
LVL 23

Accepted Solution

by:
b1xml2 earned 300 total points
ID: 6895655
Notes
=====
This XSLT Document allows for multiple clients and for which there is proper totalling, it allows works for singular clients, hence to make the code run properly, you change the first template:

<xsl:template match="/">
<table><xsl:apply-templates select="//client" /></table>
</xsl:template>
0
 
LVL 1

Author Comment

by:cmain
ID: 6895751
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.
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface In the first article: A Better Website Login System (http://www.experts-exchange.com/A_2902.html) I introduced the EE Collaborative Login System and its intended purpose. In this article I will discuss some of the design consideratio…
I will show you how to create a ASP.NET Captcha control without using any HTTP HANDELRS or what so ever. you can easily plug it into your web pages. For Example a = 2 + 3 (where 2 and 3 are 2 random numbers) Session("Answer") = 5 then we…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.

912 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now