Re: [xsl] Total of calculated values from separate templates.

Subject: Re: [xsl] Total of calculated values from separate templates.
From: Neil Williams <linux@xxxxxxxxxxxxxx>
Date: Sat, 4 Mar 2006 21:03:55 +0000
On Friday 03 March 2006 11:23 am, Neil Williams wrote:

Is it possible to calculate values from other calculated values?

No matter how I arrange it, I cannot get a simple total!

The variables are always out of scope and when I scope them, I can't sum them 
because one or other gets dumped out as NaN and the whole thing is trashed.

> From this XML:
> (a snippet of a larger file)
>
> <?xml version="1.0" encoding="UTF-8"?>
> <qof-qsf xmlns="http://qof.sourceforge.net/";>
>   <book count="1">
>     <object type="pilot_datebook" count="1">
>       <date type="start_time">2005-11-04T09:00:00Z</date>
>       <date type="end_time">2005-11-04T17:30:00Z</date>
>     </object>
>     <object type="pilot_expenses" count="2">
>       <string type="type_of_expense">Parking</string>
>       <numeric type="expense_amount">160/100</numeric>
>       <date type="expense_date">2005-11-04T00:00:00Z</date>
>     </object>
>     <object type="pilot_expenses" count="3">
>       <string type="type_of_expense">Mileage</string>
>       <numeric type="expense_amount">4000/100</numeric>
>       <date type="expense_date">2005-11-04T00:00:00Z</date>
>     </object>
>   </book>
> </qof-qsf>
>
> I can calculate the duration of the event, multiply that by a default rate
> to get an invoice entry and then process the two expenses to create their
> own invoice entries: one for parking, one for the mileage, using a default
> mileage rate. The numeric string represents amount/denominator.
>
> I can't see how to:
>  Generate a total for the entire invoice.

I still can't generate the simplest of totals - let alone subtotals for 
multiple invoices.

> basic stylesheet:
> <?xml version='1.0'?>
> <xsl:stylesheet version="1.1"
>  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>  xmlns:qof-qsf="http://qof.sourceforge.net/";
>  xmlns:html="http://www.w3.org/1999/xhtml";
>  xmlns:dt="http://xsltsl.org/date-time";
>  xmlns:date="http://exslt.org/dates-and-times";
>  xmlns:str="http://xsltsl.org/string";>
> <xsl:import href="date-time.xsl"/>
> <xsl:import href="string.xsl"/>
> <xsl:import href="./date/functions/difference/date.difference.xsl" />
> <xsl:output method="html"/>
>
> <!-- user configuration  -->
> <xsl:param name="mileage-rate">0.3</xsl:param>
> <xsl:param name="hourly-rate">20</xsl:param>
> <!-- end configuration -->
>
> <xsl:template match="/">
> <html lang="en"><head></head><body>
> <xsl:text>
> </xsl:text>
> <xsl:apply-templates
> select="/*/qof-qsf:book/qof-qsf:object[@type='pilot_datebook']"/>
> <xsl:apply-templates
> select="/*/qof-qsf:book/qof-qsf:object[@type='pilot_expenses']"/>
> <xsl:text>
> Total: </xsl:text>
>
> <xsl:text>
> </xsl:text>
> </body>
> </html>
> </xsl:template>
>
> <xsl:template
> match="/*/qof-qsf:book/qof-qsf:object[@type='pilot_datebook']">
>
> <xsl:variable name="diff_string">
> <xsl:call-template name="date:difference">
>    <xsl:with-param name="start" select="qof-qsf:date[@type='start_time']"
> /> <xsl:with-param name="end" select="qof-qsf:date[@type='end_time']" />
> </xsl:call-template>
> </xsl:variable>
> <xsl:variable name="diff_secs" select="date:seconds($diff_string)"/>
> <xsl:value-of select="floor($diff_secs div 3600)"/>
> <xsl:text> hours, </xsl:text>
> <xsl:value-of select="($diff_secs mod 3600) div 60"/>
> <xsl:text> minutes @ </xsl:text>
> <xsl:value-of select="format-number($hourly-rate, '######.00')"/>
> <xsl:text>/hr = </xsl:text>
> <xsl:param name="value">
> <xsl:value-of select="number($diff_secs div 3600 * $hourly-rate)"/>
> </xsl:param>
> <xsl:value-of select="format-number(($value), '#####.00')"/>
>
> <xsl:text>
> </xsl:text>
> </xsl:template>
>
> <xsl:template
> match="/*/qof-qsf:book/qof-qsf:object[@type='pilot_expenses']"> <xsl:param
> name="numeric_string" select="qof-qsf:numeric"/>
> <xsl:param name="before" select="substring-before($numeric_string, '/')"/>
> <xsl:param name="after" select="substring-after($numeric_string, '/')"/>
> <xsl:param name="numeric" select="$before div $after"/>
>
> <xsl:param name="type" select="qof-qsf:string[@type='type_of_expense']"/>
> <xsl:choose>
> <xsl:when test="$type='Mileage'">
> <xsl:param name="miles" select='number($numeric)'/>
> <xsl:param name="value" select="(number($miles * $mileage-rate))"/>
> <xsl:value-of select="format-number(($miles), '#####.#')"/>
> <xsl:text> miles @ </xsl:text>
> <xsl:value-of select="format-number($mileage-rate * 100, '##')"/>
> <xsl:text>p/mile = </xsl:text>
> <xsl:value-of select="format-number(($value), '#####.00')"/>
> <xsl:variable name="subtotal">
> <span><xsl:value-of select="number($value)"/></span>
> </xsl:variable>
> </xsl:when>
> <xsl:otherwise>
> <xsl:value-of select="$type"/>
> <xsl:text> = </xsl:text>
> <xsl:param name="value" select='(number($numeric))'/>
> <xsl:value-of select="format-number(($value), '#####.00')"/>
> <xsl:variable name="subtotal">
> <span><xsl:value-of select="number($value)"/></span>
> </xsl:variable>
> <xsl:text>
> </xsl:text>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:template>
>
> </xsl:stylesheet>
>
> Output from the XML above using xsltproc:
> <html lang="en">
> <head><meta http-equiv="Content-Type" content="text/html;
> charset=UTF-8"></head>
> <body>
> 8 hours, 30 minutes @ 20.00/hr = 170.00
> Parking = 1.60
> 40 miles @ 30p/mile = 12.00
> Total:
> </body>
> </html>
>
> What I wanted was:
> <html lang="en">
> <head><meta http-equiv="Content-Type" content="text/html;
> charset=UTF-8"></head>
> <body>
> 8 hours, 30 minutes @ 20.00/hr = 170.00
> Parking = 1.60
> 40 miles @ 30p/mile = 12.00
> Total: 183.60
> </body>
> </html>
>
> Do I have to create an intermediate nodeset/tree? (how?)
>
> :-)

Help!

-- 

Neil Williams
=============
http://www.data-freedom.org/
http://www.nosoftwarepatents.com/
http://www.linux.codehelp.co.uk/

Current Thread