xsl-list
[Top] [All Lists]

RE: XSL problem using sum() function

2004-11-18 11:12:01
(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="{(_at_)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(_at_)gmail(_dot_)com] 
Sent: 18 November 2004 17:29
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] 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>
      ....

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--




--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



<Prev in Thread] Current Thread [Next in Thread>