Solved

xslt + NaN

Posted on 2002-03-25
4
6,972 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

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
XSL - change date format 3 44
Problem to page 4 85
Questions about this React unit test 4 62
what are list of ebay api errors 1 18
Shoutout to Emily Plummer (http://www.experts-exchange.com/members/eplummer26.html) for giving me this article! She did most of it, I just finished it up and posted it for her :)    Introduction In a previous article (http://www.experts-exchang…
JavaScript has plenty of pieces of code people often just copy/paste from somewhere but never quite fully understand. Self-Executing functions are just one good example that I'll try to demystify here.
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…
The viewer will learn how to dynamically set the form action using jQuery.

776 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