jau
jau

Reputation: 11

How to group parent elements based on the child elements in XSLT

I am tring to group multiple elements based on the child element that has the same value. Each Child1 that has the same value should be inside of a node called Group. See desired output below. Here is a sample XML

`<?xml version="1.0" encoding="utf-8"?>
<Root>
    <Parent>
        <Child1>0123</Child1>
        <Child2>KIK</Child2>
        <Child3>YAM</Child3>
    </Parent>
    <Parent>
        <Child1>0123</Child1>
        <Child2>FIS</Child2>
        <Child3>BOL</Child3>
    </Parent>
    <Parent>
        <Child1>0123</Child1>
        <Child2>TOC</Child2>
        <Child3>INO</Child3>
    </Parent>
    <Parent>
        <Child1>456</Child1>
        <Child2>CHI</Child2>
        <Child3>KEN</Child3>
    </Parent>
    <Parent>
        <Child1>456</Child1>
        <Child2>ALA</Child2>
        <Child3>KING</Child3>
    </Parent>
</Root>`

I want the output to be like the following:

`<?xml version="1.0" encoding="utf-8"?>
<Root>
   <GROUP>  
        <Parent>
            <Child1>0123</Child1>
            <Child2>KIK</Child2>
            <Child3>YAM</Child3>
        </Parent>
        <Parent>
            <Child1>0123</Child1>
            <Child2>FIS</Child2>
            <Child3>BOL</Child3>
        </Parent>
        <Parent>
            <Child1>0123</Child1>
            <Child2>TOC</Child2>
            <Child3>INO</Child3>
        </Parent>
  </GROUP>  
  <GROUP>
        <Parent>
            <Child1>456</Child1>
            <Child2>CHI</Child2>
            <Child3>KEN</Child3>
        </Parent>
        <Parent>
            <Child1>456</Child1>
            <Child2>ALA</Child2>
            <Child3>KING</Child3>
        </Parent>
  </GROUP>  
</Root>`

I was only able to copy the whole code and not able to group it based on the values on Child1.

Upvotes: 0

Views: 44

Answers (1)

jau
jau

Reputation: 11

Sharing my solution below:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    
    <xsl:template match="@*|node()">
        
        <xsl:copy>
            
            <xsl:apply-templates select="@*|node()" />
            
        </xsl:copy>
        
    </xsl:template>
    <xsl:template match="Root">
        <Root>
            <xsl:for-each-group select="Parent" group-by="Child1">
                
                <xsl:choose>
                    <xsl:when test="count(current-group()) gt 1">
                        <Group>
                            <xsl:apply-templates select="current-group()" />
                        </Group>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()" />
                    </xsl:otherwise>
                </xsl:choose>
                
            </xsl:for-each-group>
        </Root>
        
        
        
    </xsl:template>

</xsl:stylesheet>

Upvotes: 1

Related Questions