Search code examples
xmlgroup-byxslt-1.0xslt-2.0muenchian-grouping

Grouping Nodes by hardcoding node values in XSLT


<root>
   <Entry>
      <ID>1</ID>
      <Details>
         <Code>A1</Code>
         <Value>1000</Value>
      </Details>
   </Entry>

   <Entry>
      <ID>2</ID>
      <Details>
         <Code>A2</Code>
         <Value>2000</Value>
      </Details>
   </Entry>

   <Entry>
      <ID>3</ID>
      <Details>
         <Code>B1</Code>
         <Value>3000</Value>
      </Details>
   </Entry>

   <Entry>
      <ID>4</ID>
      <Details>
         <Code>B2</Code>
         <Value>4000</Value>
      </Details>
   </Entry>
</root>

I have this input XML which I am looking to group via XSLT wherein the grouping happens by hardcoding node values. Let me explain that in detail:

The grouping needs to happen based on the Code parameter appearing in the node <Code> as follows:

  1. Codes 'A1' and 'A2' needs to be grouped together
  2. Codes 'B1' and 'B2' needs to be grouped together

I am eventually summing the values coming out of <Value> nodes in these groups. So the Output would be as follows:

<Output>
   <Code-group> A </Code-group>
   <Sum> 3000 </Sum>

   <Code-group> B </Code-group>
   <Sum> 7000 </Sum>
</Output>

For this requirement there needs to be hardcoding of the grouping values (to group A1,A2 as A and B1, B2 as B). I am using the word 'hardcoded' because the Codes (A1,A2,B1,B2) can come in any order so I want to rather hardcode the values to look for grouping than looking for Node indices.

I looked at for-each-group method as well as the Muenchian Grouping method but wasn't able to achieve the above group mapping. Any help appreciated!

Thanks in advance

EDIT: The mapping A1,A2 --> A & B1,B2 --> B is a generic example, the actual node values are entirely different than this, so a substring solution wouldn't work. That is why I was focusing on hardcoding to achieve that mapping.


Solution

  • The hardcoding requirement is difficult to understand. Perhaps you want to do something like:

    XSLT 2.0

    <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:key name="entry" match="Entry" use="Details/Code"/>
    
    <xsl:template match="/root">
        <Output>
            <Code-group> A </Code-group>
            <Sum>
                <xsl:value-of select="sum(key('entry', ('A1', 'A2'))/Details/Value)" />
            </Sum>
            <Code-group> B </Code-group>
            <Sum>
                <xsl:value-of select="sum(key('entry', ('B1', 'B2'))/Details/Value)" />
            </Sum>
        </Output>
    </xsl:template>
    
    </xsl:stylesheet>