Hi! .

I'm trying to calculate a sum of a table column in a xsl-fo file.

I iterate over a all cartoon characters found in an xml file and calculate a value of earned points for each character named "goofy".

To select the goofy-character I'm using a an if-clause within a for-each loop (see below). (I know that this could be done more elegant with an XPATH expression for this simple example).

What I need to get done, is to sum up all values that are written to the fo-file. Essentially I want to do something like this (perl-like code).

my $sum=0;
my $pointrate = 2.0;
foreach $dog @dogs
{
   if ($dog{'name'} == 'goofy')
   {
      $sum += $constants{'dog'} / $pointrate;
   }
}


XSL-Code
---------------------------------------------------------------------

<!-- body -->
<fo:table-body>
<xsl:for-each select="/comic/character[@race='dog']">
  <xsl:if test="@name='goofy'">
     <xsl:variable name="earnedPoints" select="/dogs/constants/points div    sum(//pointrate)"/>
     <fo:table-cell border="solid black 1px" padding="2pt">
        <fo:block><xsl:value-of select="$earnedPoints"/></fo:block>
     </fo:table-cell>
     <fo:table-cell border="solid black 1px">
       <fo:block font-weight="bold">some value</fo:block>
     </fo:table-cell>

  </xsl:if>
</xsl:for-each>
</fo:table-body>

-----------------------------------------------------------------------

Since variables can't change their value in XSLT I don't know how to do the sum += $constants{'dog'} / $pointrate; in XSLT.


I understand french, but not fit to express myself in french.

Thanks for help

Tschuri
Edited by Tschuri (08 May 2005 - 11:03)
Why wouldn't you try using the whole XPath expression in the evaluation of your variable? Something like...


 <xsl:variable name="earnedPoints" select="sum(/comic/character[@race='dog' and @name='goofy']/dogs/constants/points) div //pointrate"/>


By the way, the /dogs/constants... in your select attribute seems a bit strange, for it implies that there is no hierarchical relationship between your elements /comic/character and /dogs/constants. This means that both dogs and comic are direct childs of your root element. The "/" character is perhaps not useful here. In the example above, I assumed the dogs element is a child of the character element...
I think that that can help you :

//comic/caracter[count(@name)='goofy']

I've not saw what do you exactly want. But it's a Xpath query, and normally it count the number of tags who have attribute's value like 'goofy'

Ps : Sorry if I make some mistake, but I don't speak good english Smiley murf
Thank you!

I know that in this simple example it would be quite easy to calculate the sum by selecting all elements directly after the loop.

In fact, I even know that it is always possible to create an XPATH expression that selects all elements of any loop. But the XPATH expression can become very long and unreadable.

So what I want, is to build the sum of elements, almost arbitrary selected within the loop. ("Almost arbitrary" in this context means: The conditions for an element to be selected inside the loop consists of very long and complicated XPATH-Expressions and IF ane WHEN clauses).

I simplified my example by intent to make it easier to understand WHAT I want to do and I know that the information WHY I want it to do gets lost by the simplification.

So here is the complete code although I think you will be overwhelmed with the length of it.

What I want to do in this example, is to build the sum of all values of the variable $nachforderung AFTER the loop is processed.
Instead of
<xsl:variable name="summeNachforderungLSt" select="0"/>
I could forumulate an almost endless XPATH expression to get the correct result, but that is what I want to avoid.

If you prefer French just answer in French, I use English to save time and to avoid misunderstandings by my bad knowledge of French.






	<!-- Feststellung records -->
    <xsl:for-each select="/hibernate-generic/object[@class='Feststellung']">
		<xsl:variable name="feststellungID" select="./id[@name='oid']"/>		
		<xsl:variable name="feststellungsTypID" select="./property[@name='feststellungsTyp']/id[@name='oid']"/>		
		<xsl:variable name="feststellungsTypName" 
			select="/hibernate-generic/object[@class='FeststellungsTyp'][id[@name='oid']=$feststellungsTypID]/property[@name='fstName']"/>		
		<fo:block padding-top="1cm">
			<xsl:value-of select="$feststellungsTypName"/>
		</fo:block>
		
		<!-- Sachverhaltsdarstellung -->		
		<fo:block font-weight="bold" font-size="10pt" padding-top="0.5cm" color="black">
			Sachverhaltsdarstellung
		</fo:block>
		<fo:block font-size="10pt" start-indent="3mm" text-align="start">
			<xsl:variable name="kommentarID" 
				select="./property[@name='kommentar']/id"/>
			<xsl:variable name="kommentar" 
				select="/hibernate-generic/object[@class='Kommentar'][id[@name='oid']=$kommentarID]/property[@name='komText']"/>
			<xsl:value-of select="$kommentar"/>
		</fo:block>


			<fo:table padding="0.2cm">
				<fo:table-column column-width="35mm"/>
				<fo:table-column column-width="20mm"/>
				<fo:table-column column-width="35mm"/>
				<fo:table-column column-width="15mm"/>
				<fo:table-column column-width="15mm"/>
				<fo:table-column column-width="15mm"/>
				<fo:table-column column-width="15mm"/>
				<fo:table-column column-width="15mm"/>
				<fo:table-column column-width="15mm"/>
	
				<fo:table-header>
				  <fo:table-row background-color="#F0F0F0"> 
					<fo:table-cell padding="7pt" text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px">
						<fo:block font-weight="bold">Dienstnehmer</fo:block>
					</fo:table-cell>
					<fo:table-cell text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="7pt">
						<fo:block font-weight="bold">SV Nr</fo:block>
					</fo:table-cell>
					<fo:table-cell text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="7pt">
						<fo:block font-weight="bold">Zeitraum / Monat</fo:block>
					</fo:table-cell>
					<fo:table-cell text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="7pt">
						<fo:block font-weight="bold">BMG alt</fo:block>
					</fo:table-cell>
					<fo:table-cell text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="7pt">
						<fo:block font-weight="bold">Hinzu- rechnung</fo:block>
					</fo:table-cell>
					<fo:table-cell text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="7pt">
						<fo:block font-weight="bold">BMG neu</fo:block>
					</fo:table-cell>
					<fo:table-cell text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="7pt">
						<fo:block font-weight="bold">Säumnis- zuschlag</fo:block>
					</fo:table-cell>
					<fo:table-cell text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="7pt">
						<fo:block font-weight="bold">Abgaben- art</fo:block>
					</fo:table-cell>
					<fo:table-cell text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="7pt">
						<fo:block font-weight="bold">Nach- forderung</fo:block>
					</fo:table-cell>
				  </fo:table-row>
				</fo:table-header>

		
		<!-- fesDinZuord record -->
		<xsl:for-each select="./collection[@name='fesDinZuordCollection']/element[@class='FesDinZuord']">
			<xsl:variable name="fesDinZuordID" select="./id[@name='oid']"/>
			
			<xsl:variable name="dienstnehmerID" 
				select="/hibernate-generic/object[@class='Dienstnehmer'][collection[@name='fesDinZuordCollection'][element[@class='FesDinZuord'][id[@name='oid']=$fesDinZuordID]]]/id[@name='oid']"/>
			<xsl:variable name="dinStammID" 
				select="/hibernate-generic/object[@class='Dienstnehmer'][collection[@name='fesDinZuordCollection'][element[@class='FesDinZuord'][id[@name='oid']=$fesDinZuordID]]]/collection[@name='dinStammCollection']/element[@class='DinStamm']/id[@name='oid']"/>
			<xsl:variable name="dienstnehmerZuname"	
				select="/hibernate-generic/object[@class='DinStamm'][id[@name='oid']=$dinStammID]/property[@name='disFamilienname']"/>
			<xsl:variable name="dienstnehmerVorname"	
				select="/hibernate-generic/object[@class='DinStamm'][id[@name='oid']=$dinStammID]/property[@name='disVorname']"/>
			<xsl:variable name="dienstnehmerSVNr"	
				select="/hibernate-generic/object[@class='DinStamm'][id[@name='oid']=$dinStammID]/property[@name='disVsnr']"/>
			<xsl:variable name="fesZeitraumBis"	
				select="/hibernate-generic/object[@class='Feststellung'][id[@name='oid']=$feststellungID]/property[@name='fesGueltigBisDat']"/>
			<xsl:variable name="fesZeitraumVon"	
				select="/hibernate-generic/object[@class='Feststellung'][id[@name='oid']=$feststellungID]/property[@name='fesGueltigVonDat']"/>
				
				<fo:table-body font-size="8pt"> 
					<!-- Verrechnung -->
					<xsl:for-each 
						select="/hibernate-generic/object[@class='FesDinZuord'][id[@name='oid']=$fesDinZuordID]/collection[@name='verrechnungCollection']/element[@class='Verrechnung']">
						
						<xsl:variable name="verrechnungID" select="./id[@name='oid']"/>
						<xsl:variable name="bmgAlt" 
							select="/hibernate-generic/object[@class='Verrechnung'][id[@name='oid']=$verrechnungID]/property[@name='vrgGrundlageAlt']"/>
						<xsl:variable name="bmgNeu" 
							select="/hibernate-generic/object[@class='Verrechnung'][id[@name='oid']=$verrechnungID]/property[@name='vrgGrundlageNeu']"/>
						<xsl:variable name="hinzurechnung" 
							select="/hibernate-generic/object[@class='Verrechnung'][id[@name='oid']=$verrechnungID]/property[@name='vrgGrundlageDifferenz']"/>
						<xsl:variable name="saeumniszuschlag" 
							select="/hibernate-generic/object[@class='Verrechnung'][id[@name='oid']=$verrechnungID]/property[@name='vrgFKzSaeumniszuschlag']"/>
						<xsl:variable name="idAbgabenart" 
							select="/hibernate-generic/object[@class='Verrechnung'][id[@name='oid']=$verrechnungID]/property[@name='abgabenart']/id[@name='oid']"/>
						<xsl:variable name="abgabenart" 
							select="/hibernate-generic/object[@class='Abgabenart'][id[@name='oid']=$idAbgabenart]/property[@name='agaCode']"/>
							
						<xsl:variable name="abrechnungenBMGalt" 
							select="/hibernate-generic/object[@class='Abrechnung'][property[@name='verrechnung'][id[@name='oid']=$verrechnungID]]/property[@name='abrGrundlageAlt']"/>
						<xsl:variable name="abrechnungenBMGneu" 
							select="/hibernate-generic/object[@class='Abrechnung'][property[@name='verrechnung'][id[@name='oid']=$verrechnungID]]/property[@name='abrGrundlageNeu']"/>
						<xsl:variable name="summeAbrechnungBMGalt" select="sum($abrechnungenBMGalt)"/>
						<xsl:variable name="summeAbrechnungBMGNeu" select="sum($abrechnungenBMGneu)"/>
						<xsl:variable name="nachforderung" select="number($summeAbrechnungBMGNeu)-number($summeAbrechnungBMGalt)"/>
						
	
						<fo:table-row>
							<fo:table-cell display-align="center" text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
								<fo:block><xsl:value-of 
									select="concat(concat($dienstnehmerVorname,' '),$dienstnehmerZuname)"/></fo:block>
									
							</fo:table-cell>
							<fo:table-cell display-align="center" text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
								<fo:block><xsl:value-of select="$dienstnehmerSVNr"/></fo:block>
							</fo:table-cell>
							<fo:table-cell display-align="center" text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
								<fo:block>
									<xsl:call-template name="GermanDateTransformer">
										<xsl:with-param name="dateString" select="$fesZeitraumVon"/>
									</xsl:call-template>
									<xsl:text> - </xsl:text>
									<xsl:call-template name="GermanDateTransformer">
										<xsl:with-param name="dateString" select="$fesZeitraumBis"/>
									</xsl:call-template>
								</fo:block>
							</fo:table-cell>
							<fo:table-cell  display-align="center" text-align="right" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
								<fo:block><xsl:value-of select="format-number($bmgAlt,'###.###.##0,00','european')"/></fo:block>
							</fo:table-cell>
							<fo:table-cell  display-align="center" text-align="right" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
								<fo:block><xsl:value-of select="format-number($hinzurechnung,'###.###.##0,00','european')"/></fo:block>
							</fo:table-cell>
							<fo:table-cell  display-align="center" text-align="right" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
								<fo:block><xsl:value-of select="format-number($bmgNeu,'###.###.##0,00','european')"/></fo:block>
							</fo:table-cell>
							<fo:table-cell display-align="center" text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
								<fo:block><xsl:value-of select="$saeumniszuschlag"/></fo:block>
							</fo:table-cell>
							<fo:table-cell display-align="center" text-align="center" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
								<fo:block><xsl:value-of select="$abgabenart"/></fo:block>
							</fo:table-cell>
							<fo:table-cell  display-align="center" text-align="right" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
								<fo:block><xsl:value-of select="format-number($nachforderung,'###.###.##0,00','european')"/></fo:block>
							</fo:table-cell>
						</fo:table-row>
					</xsl:for-each> <!-- Verrechnung record -->
				</fo:table-body>			
			</xsl:for-each> <!-- Feststellung record -->
		</fo:table>
		<xsl:variable name="summeNachforderungLSt" select="0"/>
		<xsl:variable name="summeNachforderungDB" select="0"/>
		<xsl:variable name="summeNachforderungDZ" select="0"/>
		
		<!-- sums per Feststellung -->
		<fo:table space-before="0.5cm">
			<fo:table-column column-width="30mm"/>
			<fo:table-column column-width="30mm"/>
			<fo:table-column column-width="30mm"/>
			<fo:table-header>
				<fo:table-row background-color="#F0F0F0">
					<fo:table-cell border-bottom="none" display-align="center" number-columns-spanned="3" text-align="center" font-size="8pt" font-weight="bold" border="solid black 1px" padding="2pt">
						<fo:block>Summe Nachforderungen</fo:block>
					</fo:table-cell>
				</fo:table-row>
				
				<fo:table-row background-color="#F0F0F0">
					<fo:table-cell display-align="center" text-align="center" font-size="8pt" font-weight="bold" border="solid black 1px" padding="2pt">
						<fo:block>LSt</fo:block>
					</fo:table-cell>
					<fo:table-cell display-align="center" text-align="center" font-size="8pt" font-weight="bold" border="solid black 1px" padding="2pt">
						<fo:block>DB</fo:block>
					</fo:table-cell>
					<fo:table-cell display-align="center" text-align="center" font-size="8pt" font-weight="bold" border="solid black 1px" padding="2pt">
						<fo:block>DZ</fo:block>
					</fo:table-cell>
				</fo:table-row>
			</fo:table-header>
			<fo:table-body>
					<fo:table-row>
						<fo:table-cell display-align="center" text-align="right" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
							<fo:block><xsl:value-of select="format-number($summeNachforderungLSt,'###.###.##0,00','european')"/></fo:block>
						</fo:table-cell>
						<fo:table-cell display-align="center" text-align="right" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
							<fo:block><xsl:value-of select="format-number($summeNachforderungDB,'###.###.##0,00','european')"/></fo:block>
						</fo:table-cell>
						<fo:table-cell display-align="center" text-align="right" font-size="8pt" font-weight="normal" border="solid black 1px" padding="2pt">
							<fo:block><xsl:value-of select="format-number($summeNachforderungDZ,'###.###.##0,00','european')"/></fo:block>
						</fo:table-cell>
					</fo:table-row>
			</fo:table-body>
		</fo:table>	
	</xsl:for-each> <!-- Feststellungstyp -->
My courage is not enough to read all your code.
But from a theorical point of view and considering the way variables work in XSLT, the normal way to do what you want is to use the main and natural characteristic of a template : recursivity.
This means :
- write a template that calls itself
- give a parameter while calling
- do whatever calculation with this parameter (an addition will fit your need).