Lionel
Lionel

Reputation: 35

XSLT: How to process all elements with a child of the same value

Simply put I have XML similar to (trimmed a lot):

<Event>
  <Parameter>
    <Name>#ID</Name>
    <Value>3</Value>
  </Parameter>
  <Parameter>
    <Name>AMT</Name>
    <Value>911</Value>
  </Parameter>
</Event>
<Event>
  <Parameter>
    <Name>#ID</Name>
    <Value>3</Value>
  </Parameter>
  <Parameter>
    <Name>AMT</Name>
    <Value>10</Value>
  </Parameter>
</Event>
<Event>
  <Parameter>
    <Name>#ID</Name>
    <Value>4</Value>
  </Parameter>
  <Parameter>
    <Name>AMT</Name>
    <Value>11</Value>
  </Parameter>
</Event>

From this I want to process all Event elements that have the same "Value" for the Parameter that has a Name of "#ID". So the sample output might be:

<Result>
  <ID>3</ID>
  <AMT>10</AMT>
  <AMT>11</AMT>
<Result>
<Result>
  <ID>4</ID>
  <AMT>11</AMT>
<Result>

It is a little more complicated than that but hopefully an answer to this will be sufficient to get me unstuck. My main problem is I don't know how to collect and process together all of the Event elements that have the same Value in a Parameter with a Name of #ID.

Thanks.

Upvotes: 2

Views: 1683

Answers (1)

Tim C
Tim C

Reputation: 70598

As you are using XSLT2.0, you can use xsl:for-each-group to group your event elements by their ID in the parameter element

<xsl:for-each-group select="Event" group-by="Parameter[Name='#ID']/Value">

I am not sure if you wanted to total the "AMT" elements, or output them individually, but to output them individually, you would do this (with a separate matching template to output them)

<xsl:apply-templates select="current-group()/Parameter[Name='AMT']"/>

And to total them up you would do this

<xsl:value-of select="sum(current-group()/Parameter[Name='AMT']/Value)"/>

Here is the full XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/*">
      <xsl:for-each-group select="Event" group-by="Parameter[Name='#ID']/Value">
         <Result>
            <ID>
               <!-- <xsl:value-of select="Parameter[Name='#ID']/Value"/> -->
               <xsl:value-of select="current-grouping-key()" />
            </ID>
            <xsl:apply-templates select="current-group()/Parameter[Name='AMT']"/>
            <TOTAL_AMT>
               <xsl:value-of select="sum(current-group()/Parameter[Name='AMT']/Value)"/>
            </TOTAL_AMT>
         </Result>
      </xsl:for-each-group>
   </xsl:template>

   <xsl:template match="Parameter[Name='AMT']">
      <AMT>
         <xsl:value-of select="Value"/>
      </AMT>
   </xsl:template>
</xsl:stylesheet>

When applied to the following XML

<Events>
   <Event>
      <Parameter>
         <Name>#ID</Name>
         <Value>3</Value>
      </Parameter>
      <Parameter>
         <Name>AMT</Name>
         <Value>911</Value>
      </Parameter>
   </Event>
   <Event>
      <Parameter>
         <Name>#ID</Name>
         <Value>3</Value>
      </Parameter>
      <Parameter>
         <Name>AMT</Name>
         <Value>10</Value>
      </Parameter>
   </Event>
   <Event>
      <Parameter>
         <Name>#ID</Name>
         <Value>4</Value>
      </Parameter>
      <Parameter>
         <Name>AMT</Name>
         <Value>11</Value>
      </Parameter>
   </Event>
</Events>

The following is output

<Result>
   <ID>3</ID>
   <AMT>911</AMT>
   <AMT>10</AMT>
   <TOTAL_AMT>921</TOTAL_AMT>
</Result>
<Result>
   <ID>4</ID>
   <AMT>11</AMT>
   <TOTAL_AMT>11</TOTAL_AMT>
</Result>

Upvotes: 1

Related Questions