Garil
Garil

Reputation: 31

XSL How to sum values of elements calculated depending on an attribute of the element?

I would like to calculate values depending on an attribute of the elements differently and later sum the calculated values.

The xml structure looks like this:

<elements>
     <element type="type1">
      <value>10</value>
      <date>01.05.2012</date>
     </element>

     <element type="type2">
      <value>20</value>
      <date>02.03.2012</date>
     </element>

     <element type="type2">
      <value>20</value>
      <date>02.03.2012</date>
     </element>

</elements>

I used xsd:alternatives in the XSD to create the different "types" of elements.

The XSL looks like this:

   <xsl:for-each select="/elements">        
    <xsl:sort select="date"/> 

    <xsl:choose>
     <xsl:when test="type='type1'">
      <xsl:value-of select="value*20"/>
      <xsl:value-of select="date"/>
     </xsl:when>

     <xsl:when test="type='type1'">
      <xsl:value-of select="value*10"/>
      <xsl:value-of select="date"/>
     </xsl:when>
   </xsl:choose>

  (Here should be a sum of all the values that have been calculated.)        
  </xsl:for-each>

I want to be able to show the value after it was calculated (with a factor depending on the "type" it is.), sort the different values by their dates and display the sum of all the calculated values.

I am sure there are better ways to do what I want to do and I am happy about any suggestions.

Upvotes: 2

Views: 5888

Answers (1)

Mads Hansen
Mads Hansen

Reputation: 66781

Assuming that @type="type1" should be multiplied by 10 and@type="type2"` should be multiplied by 20, the following stylesheet:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" indent="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates select="elements/element">
            <xsl:sort select="date" />
        </xsl:apply-templates>
        <xsl:value-of select="'&#xA;'"/>
        <xsl:value-of select="sum(*/element[@type='type1']/value
                                       [number()=number()]) * 10 + 
                              sum(*/element[@type='type2']/value
                                       [number()=number()]) * 20"/>
    </xsl:template>

    <xsl:template match="element[@type='type1']/value">
        <xsl:value-of select=". * 10"/>
    </xsl:template>

    <xsl:template match="element[@type='type2']/value">
        <xsl:value-of select=". * 20"/>
    </xsl:template>

    <!-- this matches any of the value elements who's values are not a number -->
    <xsl:template match="element[@type]/value[number()!=number()]">
        <xsl:text>0</xsl:text>
    </xsl:template>

</xsl:stylesheet>

produces the following output:

    100
    01.05.2012

    400
    02.03.2012

    400
    02.03.2012

900

Upvotes: 1

Related Questions