[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] RE: XSL problem using sum() function
(Dave P: could we have this in the FAQ please?) The general problem of summing over a computed value has three noteworthy solutions. Let's use f($x) for the function that computes the number you want to total, given a node $x (the canonical example is summing price times quantity, where f() is $x/@price * $x/@qty), and let's use $seq for the sequence of nodes that you want to sum over. That is, you want to apply f() to each node in $seq and return the sum of the results. (a) In XPath 2.0 sum(for $i in $seq return f($i)) In fact, in the Oct 2004 draft it's even simpler, but this won't be available until Saxon 8.2: sum($seq/f(.)) Concrete examples: sum(//item/(@price * @qty)) sum(//item/number(translate(., '$', ''))) (b) In XSLT 1.0 with xx:node-set() extension Create a result-tree-fragment containing the computed numeric values as values of element or attribute nodes; use xx:node-set() to convert this RTF to a node-set, and then use sum() over the nodes. For example: <xsl:variable name="temp"> <xsl:for-each select="$seq"> <item value="{f(.)}"/> </xsl:for-each> </xsl:variable> or more concretly, <xsl:variable name="temp"> <xsl:for-each select="//item"> <item value="{@price * @qty}"/> </xsl:for-each> </xsl:variable> <xsl:value-of select="sum(xx:node-set($temp)/item/@value)"/> (c) In pure XSLT 1.0 Recurse over the input sequence using a recursive named template: <xsl:template name="total"> <xsl:param name="seq"/> <xsl:param name="total-so-far" select="0"/> <xsl:choose> <xsl:when test="$seq"> <xsl:call-template name="total"> <xsl:with-param name="seq" select="$seq[position()!=1]"/> <xsl:with-param name="total-so-far" select="$total-so-far + f($seq[1])"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$total-so-far"/> </xsl:otherwise> </xsl:choose> </xsl:template> Michael Kay http://www.saxonica.com/ > -----Original Message----- > From: Christopher Hansen [mailto:chansen1@xxxxxxxxx] > Sent: 18 November 2004 17:29 > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx > Subject: XSL problem using sum() function > > Im trying to get the sum of all salaries for company:BG (see XML > below). Im using translate to remove the '$' and ',' from the dollar > amounts and then, trying to sum them up. But i get the error that it > cannot convert String to NodeList. I've tried some other workarounds > but i just cant seem to get it. Any ideas? > Thanks > Chris > > > The XSL: > > <?xml version="1.0"?> > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > version="1.0"> > > <xsl:output method="html"/> > > <xsl:variable name="workssection" > select="document('works.xml')" /> > <xsl:variable name="empsection" > select="document('employees.xml')" /> > > <xsl:template match="/"> > <xsl:for-each select="$workssection//works-for/" > > <xsl:if test ="company-name = 'BG'" > > <xsl:variable name="trans" > select="translate(salary,'$,','')" /> > <p><xsl:value-of select="sum($trans)" /></p> > </xsl:if> > </xsl:for-each> > > </xsl:template> > </xsl:stylesheet> > > > > A portion of the XML file: > <works> > <works-for> > <emp-name>John Doe</emp-name> > <company-name>BG</company-name> > <company-city>Ames</company-city> > <salary>$70,000</salary> > </works-for> > > <works-for> > <emp-name>Margaret Thatcher</emp-name> > <company-name>BG</company-name> > <company-city>London</company-city> > <salary>$7,000,000</salary> > </works-for> > ....
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|