xsl-list
[Top] [All Lists]

Re: Storing Partial Sums

2004-09-08 12:47:34
Hi Fatih,

Guessing (from your XSL snippet) how your input looks like:

<DocRoot>
 <Documents>
  <Document Doc_No="123">
   <People>
    <Person Person_Id="JB-007" Avg="1000"/>
    <Person Person_Id="KL-008" Avg="800"/>
    <Person Person_Id="JP-123" Avg="1400"/>
   </People>
  </Document>
  <Document Doc_No="456">
   <People>
    <Person Person_Id="JB-007" Avg="200"/>
    <Person Person_Id="KL-008" Avg="300"/>
   </People>
  </Document>
  <Document Doc_No="789">
   <People>
    <Person Person_Id="JB-007" Avg="600"/>
    <Person Person_Id="MT-111" Avg="500"/>
   </People>
  </Document>
 </Documents>
</DocRoot>

and (still guessing) what exactly you want to achieve: totals and/or averages 
by @Person_Id?
Seems like a typical case for Muenchian Grouping:
http://www.jenitennison.com/xslt/grouping/muenchian.html

With a key, you can access all the <Person> elements by their Person_Id 
attribute:

<xsl:key name="persons" use="@Person_Id"
    match="/DocRoot/Documents/Document/People/Person"/>

and then use this to generate a list of unique @Person_Id's with:

    select="Person[count(. | key('persons', @Person_Id)[1]) = 1]"

Here's a stylesheet that calculates sums and averages from the input above:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
 <xsl:output method="xml" version="1.0" indent="yes"/>
 <xsl:key name="persons" use="@Person_Id" 
match="/DocRoot/Documents/Document/People/Person"/>
 <xsl:template match="/DocRoot/Documents">
  <Result>
   <People>
    <xsl:apply-templates select="Document/People/Person[count(. | 
key('persons', @Person_Id)[1]) = 1]">
     <xsl:sort select="@Person_Id"/>
    </xsl:apply-templates>
   </People>
   <Totals>
    <xsl:variable name="num" select="count(Document/People/Person)"/>
    <xsl:variable name="sum" select="sum(Document/People/Person/@Avg)"/>
    <Num><xsl:value-of select="$num"/></Num>
    <Sum><xsl:value-of select="$sum"/></Sum>
    <Avg><xsl:value-of select="format-number($sum div $num, '#.##')"/></Avg>
   </Totals>
  </Result>
 </xsl:template>
 <xsl:template match="Person">
  <Person Person_Id="{(_at_)Person_Id}">
   <xsl:variable name="num" select="count(key('persons', @Person_Id))"/>
   <xsl:variable name="sum" select="sum(key('persons', @Person_Id)/@Avg)"/>
   <Num><xsl:value-of select="$num"/></Num>
   <Sum><xsl:value-of select="$sum"/></Sum>
   <Avg><xsl:value-of select="format-number($sum div $num, '#.##')"/></Avg>
  </Person>
 </xsl:template>
</xsl:stylesheet>

gives this output:

<Result>
   <People>
      <Person Person_Id="JB-007">
         <Num>3</Num>
         <Sum>1800</Sum>
         <Avg>600</Avg>
      </Person>
      <Person Person_Id="JP-123">
         <Num>1</Num>
         <Sum>1400</Sum>
         <Avg>1400</Avg>
      </Person>
      <Person Person_Id="KL-008">
         <Num>2</Num>
         <Sum>1100</Sum>
         <Avg>550</Avg>
      </Person>
      <Person Person_Id="MT-111">
         <Num>1</Num>
         <Sum>500</Sum>
         <Avg>500</Avg>
      </Person>
   </People>
   <Totals>
      <Num>7</Num>
      <Sum>4800</Sum>
      <Avg>685.71</Avg>
   </Totals>
</Result>

HTH
Anton Triest


Fatih TURKMEN wrote:

Hi,
I am trying to get the sum of all values in a for-each
loop. Is it possible to store the partial sums to find
the final result?

xsl is something like this :

<xsl:for-each  select
="Documents/Document[(_at_)Doc_No=$lastdoc]/People/Person">

<xsl:variable name="person" select="@Person_Id"/> 
<xsl:variable name="week"
select="count(/DocRoot/Documents/Document/People/Person[(_at_)Person_Id=$person])"/>

<xsl:value-of select="format-number
    
(sum(/DocRoot/Documents/Document/People/Person[(_at_)Person_Id=$person]/@Avg)
    div  $week, '##.##')"/> 
</xsl:for-each>

For the above xsl snippet what I am  trying to do is to get the sum of all   
"sum(/DocRoot/Documents/Document/People/Person[(_at_)Person_Id=$kisi]/@Avg)
div  $week "    values. I tried to write an XPath expression to find the sum 
but 
couldn't success. So I need to store the partial sums to find the result.

Any idea?



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