[xsl] Re: Re: max of sum

Subject: [xsl] Re: Re: max of sum
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Fri, 1 Feb 2002 01:28:45 -0800 (PST)
> > Is there a way to get the max for a bunch of sum on an attribute. 
> 
> Yes, of course.
> 
> > I have the following XML and would like to find what's the highest
expenses 
> > (sum of all expense/@value). Which would be 303 . 
> > any idea ? 
> >  
> > <company> 
> >    <department id="IT"> 
> >       <expense value="10"/> 
> >       <expense value="12"/> 
> >       <expense value="13"/> 
> >       <expense value="18"/> 
> >       <expense value="28"/> 
> >    </department> 
> >  
> >    <department id="Research"> 
> >       <expense value="40"/> 
> >       <expense value="150"/> 
> >       <expense value="75"/> 
> >       <expense value="17"/> 
> >       <expense value="21"/> 
> >    </department> 
> >  
> >    <department id="Finance"> 
> >       <expense value="34"/> 
> >       <expense value="77"/> 
> >    </department> 
> >  
> >    <department id="HR"> 
> >       <expense value="22"/> 
> >    </department> 
> > </company> 
> 
> 
> <xsl:template match="department">
>   <xsl:variable name="sum" select="sum(expense/@value)" />
>   <xsl:if test="not(../department[sum(expense/@value) > $sum])">
>     <xsl:text />max: <xsl:value-of select="$sum" /> for <xsl:text />
>     <xsl:value-of select="@id" />
>   </xsl:if>
> </xsl:template>

This above solution will calculate the sum of expenses for each
department N times (where N is the number of the department elements).

Here's a functional solution:

<xsl:stylesheet version = "1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:test-map-sum="test-map-sum"
  exclude-result-prefixes = "xsl test-map-sum" >

    <xsl:import href = "sum.xsl" />
    <xsl:import href = "map.xsl" />
    <xsl:import href = "maximum.xsl" />

    <test-map-sum:test-map-sum/>

    <xsl:output method = "text" />

    <xsl:template match = "/" >
      <!-- Get: map sum department (expense/@value) -->
      <xsl:variable name = "vdeptSums" >

        <xsl:variable name = "vTestMap"
                      select = "document('')/*/test-map-sum:*[1]" />

        <xsl:call-template name = "map" >
          <xsl:with-param name = "pFun" select = "$vTestMap" />
          <xsl:with-param name = "pList1" 
                          select = "/company/department" />
        </xsl:call-template>
      </xsl:variable>

      <!-- Get maximum map sum department (expense/@value) -->
      <xsl:call-template name = "maximum" >
        <xsl:with-param name = "pList"
                        select = "msxsl:node-set($vdeptSums)/*" />
      </xsl:call-template>
  </xsl:template>

  <xsl:template name = "makeSum" match = "test-map-sum:*" >
    <xsl:param name = "arg1" />

    <xsl:call-template name = "sum" >
      <xsl:with-param name = "pList" select = "$arg1/*/@value" />
    </xsl:call-template>
  </xsl:template>

</xsl:stylesheet>

When applied to the given source xml document, it produces the correct
result: 303.

In the same way one can calculate the sum of products, product of sums,
... etc., which seems to be difficult to achieve in XPath 2.0.

Cheers,
Dimitre Novatchev.



__________________________________________________
Do You Yahoo!?
Great stuff seeking new owners in Yahoo! Auctions! 
http://auctions.yahoo.com

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


Current Thread