Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

xslt + NaN

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

Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
Many times as a report developer I've been asked to display normalized data such as three rows with values Jack, Joe, and Bob as a single comma-separated string such as 'Jack, Joe, Bob', and vice versa.  Here's how to do it. 
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.

828 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