Search code examples
xmlxsltxslt-2.0xslt-grouping

Grouping Child nodes under each Parent nodes in XSLT


I am new to the XSLT grouping concept. I am trying to group the below XML using XSLT 2.0 .

<Root>
    <Entry>
        <Split>
            <Data>
                <Num>20</Num>
                <Type>A</Type>
            </Data>
            <Data>
                <Num>20</Num>
                <Type>A</Type>
            </Data>
            <Data>
                <Num>20</Num>
                <Type>A</Type>
            </Data>
        </Split>
        <Split>
            <Data>
                <Num>20</Num>
                <Type>B</Type>
            </Data>
            <Data>
                <Num>20</Num>
                <Type>B</Type>
            </Data>
        </Split>
        <Split>
            <Data>
                <Num>21</Num>
                <Type>C</Type>
            </Data>
            <Data>
                <Num>21</Num>
                <Type>C</Type>
            </Data>
        </Split>        
    </Entry>
</Root>

And below is my expected output.

<Root>
    <Entry>
        <Split>
            <New_Tag>
                <Data>
                    <Num>20</Num>
                    <Type>A</Type>
                </Data>
                <Data>
                    <Num>20</Num>
                    <Type>A</Type>
                </Data>
                <Data>
                    <Num>20</Num>
                    <Type>A</Type>
                </Data>
            </New_Tag>
            <New_Tag>
                <Data>
                    <Num>20</Num>
                    <Type>B</Type>
                </Data>
                <Data>
                    <Num>20</Num>
                    <Type>B</Type>
                </Data>
            </New_Tag>
        </Split>
        <Split>
            <New_Tag>
                <Data>
                    <Num>21</Num>
                    <Type>A</Type>
                </Data>
                <Data>
                    <Num>21</Num>
                    <Type>A</Type>
                </Data>
            </New_Tag>
        </Split>
    </Entry>
</Root>

I want to group 'Data' tags under 'Split'to 'New_Tag' if it has same 'Num' value in XSLT 2.0 . There will be more report entry. Please help me with this.

Is there ant way to this?

Thanks in advance.


Solution

  • You could group the Split elements by Data/Num and rename the Split's to New_Tag.

    Example...

    XML Input

    <Root>
        <Entry>
            <Split>
                <Data>
                    <Num>20</Num>
                    <Type>A</Type>
                </Data>
                <Data>
                    <Num>20</Num>
                    <Type>A</Type>
                </Data>
                <Data>
                    <Num>20</Num>
                    <Type>A</Type>
                </Data>
            </Split>
            <Split>
                <Data>
                    <Num>20</Num>
                    <Type>B</Type>
                </Data>
                <Data>
                    <Num>20</Num>
                    <Type>B</Type>
                </Data>
            </Split>
            <Split>
                <Data>
                    <Num>21</Num>
                    <Type>C</Type>
                </Data>
                <Data>
                    <Num>21</Num>
                    <Type>C</Type>
                </Data>
            </Split>        
        </Entry>
    </Root>
    

    XSLT 2.0

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="Entry">
        <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:for-each-group select="Split" group-by="Data/Num">
            <xsl:copy>
              <xsl:apply-templates select="current-group()"/>
            </xsl:copy>
          </xsl:for-each-group>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="Split">
        <New_Tag>
          <xsl:apply-templates select="@*|node()"/>
        </New_Tag>
      </xsl:template>
    
    </xsl:stylesheet>
    

    XML Output

    <Root>
       <Entry>
          <Split>
             <New_Tag>
                <Data>
                   <Num>20</Num>
                   <Type>A</Type>
                </Data>
                <Data>
                   <Num>20</Num>
                   <Type>A</Type>
                </Data>
                <Data>
                   <Num>20</Num>
                   <Type>A</Type>
                </Data>
             </New_Tag>
             <New_Tag>
                <Data>
                   <Num>20</Num>
                   <Type>B</Type>
                </Data>
                <Data>
                   <Num>20</Num>
                   <Type>B</Type>
                </Data>
             </New_Tag>
          </Split>
          <Split>
             <New_Tag>
                <Data>
                   <Num>21</Num>
                   <Type>C</Type>
                </Data>
                <Data>
                   <Num>21</Num>
                   <Type>C</Type>
                </Data>
             </New_Tag>
          </Split>
       </Entry>
    </Root>