[xsl] Re: Using sum to Produce a total from combined documents

Subject: [xsl] Re: Using sum to Produce a total from combined documents
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Tue, 2 Jul 2002 13:09:17 -0700 (PDT)
--- "Eric Vitiello Jr." <xsl-list at perceive dot net> wrote:

> 
> I need to get a total using a calculation.
> 
> I have two files, one containing current stock information, and the
> second
> contains short stock information, and the number of shares owned.
> 
> I need to take the last-sale-price, multiply it by the @shares (in
> config)
> and produce a total.  I have this completed, and it wasn't a problem.
> 
> I need to create a total for this column though - it should produce a
> total
> value of the portfolio. (adding up all of the values discussed in the
> last paragraph.)  This would be inserted where the phrase "TOTAL
> HERE"
> is below.
> 
> I'd greatly appreciate a solution for this.  I'm quite sure the
> solution is simple,
> but it's eluding me.
> 
> XML and XSLT files are below.
> 
> --
> Eric Vitiello [Perceive Designs]
> <http://www.perceive.net>
> Got Geek? <http://www.cafepress.com/got_geek>
> 
> 
> (I've removed some data for ease of reading and explanation)
> 
> stock.xml
> -------------------------------
> <nasdaqamex-dot-com>
> 	<equity-quote symbol="DIS">
> 		<issue-name>DISNEY CO WALT HLDG CO</issue-name>
> 		<last-sale-price>18.27</last-sale-price>
> 	</equity-quote>
> 	<equity-quote symbol="SYQTQ">
> 		<issue-name>Syquest</issue-name>
> 		<last-sale-price>.02</last-sale-price>
> 	</equity-quote>
> </nasdaqamex-dot-com>
> -------------------------------
> 
> config.xml
> -------------------------------
> <config>
> 	<stocks>
> 		<stock symbol="DIS" type="stock" shares="40"/>
> 		<stock symbol="SYQTQ" type="stock" shares="200"/>
> 	</stocks>
> </config>
> -------------------------------
> 
> 
> my XSL, which is being applied to stock.xml:
> -------------------------------
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";;
> version="1.0">
>   <xsl:output method="html" indent="yes" />
> 	<xsl:variable name="config" select="document('config.xml')/config"
> />
> 
> 	<xsl:template match="nasdaqamex-dot-com">
> 		<div id="stocks">
> 			<table cellspacing="0" cellpadding="1" width="100%">
> 				<tr>
> 					<th>name</th>
> 					<th>symbol</th>
> 					<th>last</th>
> 					<th>value</th>
> 				</tr>
> 				<xsl:apply-templates select="index-quote" />
> 				<xsl:apply-templates select="equity-quote" />
> 				<tr><td align="right" colspan="7">Total Value</td><td>TOTAL
> HERE</td></tr>
> 			</table>
> 		</div>
> 	</xsl:template>
> 	
> 	<xsl:template match="equity-quote">
> 		<tr>
> 			<xsl:attribute name="class">
> 				<xsl:choose>
> 					<xsl:when test="number(net-change-price) &lt;
> 0">priceDown</xsl:when>
> 					<xsl:otherwise>priceUp</xsl:otherwise>
> 				</xsl:choose>
> 			</xsl:attribute>
> 			<xsl:variable name="currentSymbol" select="@symbol"/>
> 			<td><xsl:value-of select="issue-name"/></td>
> 			<td><xsl:value-of select="@symbol" /></td>
> 			<td><xsl:value-of select="last-sale-price"/></td>
> 			<td><xsl:value-of
>
select="format-number(($config/stocks/stock[@symbol=$currentSymbol]/@shares
> * last-sale-price),'$###,##0.00;($###,##0.00)')"/></td>
> 		</tr>
> 	</xsl:template>
> </xsl:stylesheet>
> -------------------------------


Hi Eric,

You can calculate the sum in different ways using the FXSL library. The
simplest is when the prices from stock.xml are ordered (corresponding
1:1) exactly to match the ordering of stocks in config.xml. In this
case the simplest solution is to use the zipWith() function in order to
get a list with the total amounts for the sales of each stock, then
pass this list to the sum() function.

In the case, when such ordering cannot be assumed, there is a solution
using the foldl() function:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:foldl-func="f:foldl-func"
exclude-result-prefixes="xsl foldl-func"
>

   <xsl:import href="foldl.xsl"/>
   
   <xsl:output  encoding="UTF-8" omit-xml-declaration="yes"/>

   <!-- This transformation must be applied to:
        stock.xml 
     -->
   <foldl-func:foldl-func/>
   <xsl:variable name="vFoldlFun" 
                 select="document('')/*/foldl-func:*[1]"/>

    <xsl:template match="/">

      <xsl:call-template name="foldl">
        <xsl:with-param name="pFunc" select="$vFoldlFun"/>
        <xsl:with-param name="pList" select="/*/equity-quote"/>
        <xsl:with-param name="pA0" select="0"/>
      </xsl:call-template>
    </xsl:template>

    <xsl:template match="foldl-func:*">
         <xsl:param name="arg1" select="0"/> <!-- accumulator -->
         <xsl:param name="arg2" select="/.."/>
         
         <xsl:value-of 
          select="$arg1 
                + 
                  $arg2/last-sale-price 
                * 
                  document('config.xml')/*/*/stock[@symbol 
                                                  = 
                                                   $arg2/@symbol
                                                   ]
                                                    /@shares"/>
    </xsl:template>

</xsl:stylesheet>

When the above transformation is applied to the stock.xml file:

<nasdaqamex-dot-com>
	<equity-quote symbol="DIS">
		<issue-name>DISNEY CO WALT HLDG CO</issue-name>
		<last-sale-price>18.27</last-sale-price>
	</equity-quote>
	<equity-quote symbol="SYQTQ">
		<issue-name>Syquest</issue-name>
		<last-sale-price>.02</last-sale-price>
	</equity-quote>
</nasdaqamex-dot-com>

the result is:

734.8


Cheers,
Dimitre Novatchev.

__________________________________________________
Do You Yahoo!?
Sign up for SBC Yahoo! Dial - First Month Free
http://sbc.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread