Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Does XSL ADD up?

Status
Not open for further replies.

CubeE101

Programmer
Nov 19, 2002
1,492
US
OK...

Let's say I have this segment in an XML file...
Code:
<Order>
  <Number>12345</Number>
  <Part>
    <ID>112233</ID>
    <Cost>5.00</Cost>
    <QTY>5</QTY>
  <Part>
  <Part>
    <ID>112244</ID>
    <Cost>10.00</Cost>
    <QTY>2</QTY>
  <Part>
</Order>

And I want the HTML output to look like:
Code:
<table>
 <tr>
  <th>Part ID</td>
  <th>QTY</td>
  <th>Cost</td>
  <th>Total</td>
 </tr>
 <tr>
  <td>112233</td>
  <td>5</td>
  <td>5.00</td>
  <td>25.00</td>
 </tr>
 <tr>
  <td>112244</td>
  <td>2</td>
  <td>10.00</td>
  <td>20.00</td>
 </tr>
</table>

Is there a way to make XSL add values?
Or do you have to calculate everything and place it in the XML somewhere prior to translation?

I want something like...
Code:
<table>
 <tr>
  <th>Part ID</td>
  <th>QTY</td>
  <th>Cost</td>
  <th>Total</td>
 </tr>
 <xsl:for-each select="//Order">
  <tr>
   <td><xsl:value-of select="ID"/></td>
   <td><xsl:value-of select="QTY"/></td>
   <td><xsl:value-of select="Cost"/></td>
   <td><xsl:value-of select="[b]QTY * Cost[/b]"/></td>
  </tr>
 </xsl:for-each>
</table>

Any suggestions???


PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
btw...

I know...
<xsl:for-each select="//Order">
should be...
<xsl:for-each select="//Order/Part">
This was just something I typed up real quick for the question...

I just want to know if you can do math operations in XSL...

Also, is there a way to add up the Totals? (I forgot About That Part...

Thanks in advance...
-Josh


PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
Example

XML File (save as Sales.XML):
<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="transform.xsl"?>
<sales>
<summary>
<heading>Lucerne Publishing</heading>
<subhead>Regional Sales Report</subhead>
<description>Sales report for the West Coast, Central and East Coast regions.</description>
</summary>
<data>
<region>
<name>West Coast</name>
<quarter number="1" books_sold="24000" />
<quarter number="2" books_sold="38600" />
<quarter number="3" books_sold="44030" />
<quarter number="4" books_sold="21000" />
</region>
<region>
<name>Central</name>
<quarter number="1" books_sold="11000" />
<quarter number="2" books_sold="16080" />
<quarter number="3" books_sold="25000" />
<quarter number="4" books_sold="29000" />
</region>
<region>
<name>East Coast</name>
<quarter number="1" books_sold="27000" />
<quarter number="2" books_sold="31400" />
<quarter number="3" books_sold="40100" />
<quarter number="4" books_sold="30000" />
</region>
</data>
</sales>

XSLT File (save as Transform.xslt):
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl=" version="1.0">
<xsl:eek:utput method="html"/>
<xsl:param name="low_sales" select="21000"/>
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE><xsl:value-of select="//summary/heading"/></TITLE>
</HEAD>
<BODY>
<h1><xsl:value-of select="//summary/heading"/></h1>
<h2><xsl:value-of select="//summary/subhead"/></h2>
<p><xsl:value-of select="//summary/description"/></p>

<table>
<tr>
<th>Region\Quarter</th>
<xsl:for-each select="//data/region[1]/quarter">
<th>Q<xsl:value-of select="@number"/></th>
</xsl:for-each>
<th>Total</th>
</tr>
<xsl:for-each select="//data/region">
<tr>
<th style="text-align:left"><xsl:value-of select="name"/></th>
<xsl:for-each select="quarter">
<td>
<xsl:attribute name="style">
<xsl:choose>
<xsl:when test="number(@books_sold &lt;= $low_sales)">color:red;</xsl:when>
<xsl:eek:therwise>color:green;</xsl:eek:therwise>
</xsl:choose>
text-align:right;
</xsl:attribute>
<xsl:value-of select="format-number(@books_sold,'###,###')"/>
</td>

</xsl:for-each>
<td style="text-align:right;font-weight:bold;">
<xsl:value-of select="format-number(sum(quarter/@books_sold),'###,###')"/>
</td>
</tr>
</xsl:for-each>
</table>

</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>

Place both files in the same directory then open Sales.xml in your web browser.

For further info lookup "XSLT, Concepts" in MSDN.

HTH

Smeat
 
Thanks, But I already tried the Sum() method, yet I can't get it to do what I want, because it only returns the sum of a Node-Set...

It would work if there was a way to create a temporary Node-Set...

Since I posted this, I have been experimenting with it and this is what I have so far:

temp.xml
Code:
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="temp.xslt"?>
<Order>
  <Number>12345</Number>
  <Part>
    <ID>112233</ID>
    <Cost>5.00</Cost>
    <QTY>5</QTY>
  </Part>
  <Part>
    <ID>112244</ID>
    <Cost>10.00</Cost>
    <QTY>2</QTY>
  </Part>
</Order>
temp.xslt
Code:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]

[b]<xsl:variable name="totals" select="0" />[/b]
<xsl:template match="/">
<html>
<body>

<table>
 <tr>
  <th>Part ID</th>
  <th>QTY</th>
  <th>Cost</th>
  <th>Total</th>
 </tr>
 <xsl:for-each select="//Order/Part">
  <tr>
   <td><xsl:value-of select="ID"/></td>
   <td><xsl:value-of select="QTY"/></td>
   <td><xsl:value-of select="Cost"/></td>
   <td name="Total"><xsl:value-of select="QTY * Cost"/></td>
   [b]<xsl:variable name="totals" select="$totals + QTY * Cost" />[/b]
  </tr>
 </xsl:for-each>
 <tr>
  <td></td>
  <td></td>
  <td>Total</td>
  <td>[b]<xsl:value-of select="$totals"/>[/b]</td>
 </tr>
</table>

</body>
</html>
</xsl:template>
</xsl:stylesheet>

*Note: the above code works...
The bold areas are what I would like to do, they do not return an error, yet the do not work as desired either...

Sum would work, except the individual QTY might change...
otherwise, I could say...
<td><xsl:value-of select="sum(//Cost)"/></td>


-----------------------------------------------------
OK... Just figured it out with the help of:


here is the XSL:
Code:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]

 <xsl:variable name="totals">
   0
   <xsl:for-each select="//Order/Part">
    + <xsl:value-of select="QTY * Cost"/>
   </xsl:for-each>
 </xsl:variable>

<xsl:template match="/">
<html>
<body>

<table border="1">
 <tr>
  <th>Part ID</th>
  <th>QTY</th>
  <th>Cost</th>
  <th>Total</th>
 </tr>
 <xsl:for-each select="//Order/Part">
  <tr>
   <td><xsl:value-of select="ID"/></td>
   <td><xsl:value-of select="QTY"/></td>
   <td><xsl:value-of select="Cost"/></td>
   <td><xsl:value-of select="QTY * Cost"/></td>
  </tr>
 </xsl:for-each>

 [b]<xsl:variable name="Items" select="//Part"/>
 <xsl:variable name="TotalValue">
  <xsl:call-template name="Total">
   <xsl:with-param name="Items" select="$Items"/>
   <xsl:with-param name="RunningTotal"    select="0"/>
  </xsl:call-template>
 </xsl:variable>[/b]

 <tr>
  <td colspan="4">Total = <xsl:value-of select="[b]$TotalValue[/b]"/></td>
 </tr>
</table>

</body>
</html>
</xsl:template>

[b] <xsl:template name="Total">
  <xsl:param name="Items"/>
  <xsl:param name="RunningTotal"/>
  <xsl:choose>
   <xsl:when test="not($Items)">
    <xsl:copy-of select="$RunningTotal"/>
   </xsl:when>
   <xsl:otherwise>
  <xsl:variable name="CurrentTotal" select="$RunningTotal + ($Items[1]/QTY * $Items[1]/Cost)"/>
   <xsl:call-template name="Total">
    <xsl:with-param name="Items" select="$Items[position()>1]"/>
    <xsl:with-param name="RunningTotal" select="$CurrentTotal"/>
   </xsl:call-template>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>[/b]

</xsl:stylesheet>

It's recursive template, so it loops through each node until it is done, as a recursive function would do in a program...


PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top