Victor
Victor

Reputation: 333

Removing duplicates in parent and child entity in XSLT

I have a sample message in which I need to remove duplicate within the block of temperatureInformation and temperatureStats.

The sample message is

<document>
<body>
    <party>
        <gtin>1000909090</gtin>
        <pos>
            <attrGroupMany name="temperatureInformation">
                <row>
                    <gtin>1000909090</gtin>
                    <attr name="temperatureCode">STORAGE</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        <value qual="CC">20</value>
                    </attrQualMany>
                    <attrGroupMany name="temperatureStats">
                        <row>
                            <attr name="StatsCode">CODE1</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE2</attr>
                        </row>
                    </attrGroupMany>
                </row>
                <row>
                    <attr name="temperatureCode">STORAGE</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        <value qual="CC">20</value>
                    </attrQualMany>
                    <attrGroupMany name="temperatureStats">
                        <row>
                            <attr name="StatsCode">CODE1</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE3</attr>
                        </row>
                    </attrGroupMany>
                </row>
                <row>
                    <attr name="temperatureCode">HANDLING</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>                    
                    </attrQualMany>
                    <attrGroupMany name="temperatureStats">
                        <row>
                            <attr name="StatsCode">CODE5</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE6</attr>
                        </row>
                    </attrGroupMany>
                </row>
                <row>
                    <attr name="temperatureCode">HANDLING</attr>
                    <attrGroupMany name="temperatureStats">
                        <row>
                            <attr name="StatsCode">CODE7</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE8</attr>
                        </row>
                    </attrGroupMany>
                </row>
            </attrGroupMany>
        </pos>
    </party>    
</body>
</document>

I am using the below XSLT in which duplicate of the parent which is temperatureInformation is removed but duplicate within the child temperatureStats are not removed

The expected output is

<document>
 <body>
    <party>
        <gtin>1000909090</gtin>
        <pos>
            <attrGroupMany name="temperatureInformation">
                <row>
                    <gtin>1000909090</gtin>
                    <attr name="temperatureCode">STORAGE</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        <value qual="CC">20</value>
                    </attrQualMany>
                    <attrGroupMany name="temperatureStats">
                        <row>
                            <attr name="StatsCode">CODE1</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE2</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE3</attr>
                        </row>
                    </attrGroupMany>
                </row>
                <row>
                    <attr name="temperatureCode">HANDLING</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>                    
                    </attrQualMany>
                    <attrGroupMany name="temperatureStats">
                        <row>
                            <attr name="StatsCode">CODE5</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE6</attr>
                        </row>
                    </attrGroupMany>
                </row>
                <row>
                    <attr name="temperatureCode">HANDLING</attr>
                    <attrGroupMany name="temperatureStats">
                        <row>
                            <attr name="StatsCode">CODE7</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE8</attr>
                        </row>
                    </attrGroupMany>
                </row>
            </attrGroupMany>
        </pos>
    </party>    
</body>
</document>

XSLT used is

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">



    <xsl:key name="grouptemperatureInformation" match="party/pos/attrGroupMany[@name = 'temperatureInformation']/row"
    use="concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature'])"/>

    <xsl:key name="grouptemperatureStats" match="party/pos/attrGroupMany[@name = 'temperatureInformation']/row/attrGroupMany[@name = 'temperatureStats']/row"
    use="concat(generate-id(ancestor::pos), '|', attr[@name = 'StatsCode'])"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="attrGroupMany[@name = 'temperatureInformation']">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="row[generate-id() = generate-id(key('grouptemperatureInformation', concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature']))[1])]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="attrGroupMany[@name = 'temperatureStats']">
        <xsl:copy>
            <xsl:apply-templates select="@* | key('grouptemperatureInformation', concat(generate-id(ancestor::pos), '|',../attr[@name = 'temperatureCode'], '|', ../attrQualMany[@name = 'temperature']))/attrGroupMany[@name = 'temperatureStats']/row"/> 

            <!-- <xsl:apply-templates select="@*"/> 
        <xsl:apply-templates select="row[generate-id() = generate-id(key('grouptemperatureStats', concat(generate-id(ancestor::pos), '|', attr[@name = 'StatsCode']))[1])]"/> -->
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Can anyone guide me where I am going wrong.

Upvotes: 0

Views: 270

Answers (1)

Tim C
Tim C

Reputation: 70618

As well as removing the duplicate "temperatureInformation" elements, for each such distinct element it looks like you want to merge the distinct "temperatureStats" elements for all elements in the group.

As this is a second level of grouping, the key for this will need to take into the first level of grouping too, and so look like this:

<xsl:key name="grouptemperatureStats" 
         match="party/pos/attrGroupMany[@name = 'temperatureInformation']/row/attrGroupMany[@name = 'temperatureStats']/row"
         use="concat(generate-id(ancestor::pos), '|', ../../../attr[@name = 'temperatureCode'], '|', ../../../attrQualMany[@name = 'temperature'], '|', attr[@name = 'StatsCode'])"/>

To use it, in a template matching the "temperatureStats" element, you would first select all the elements in the current parent group

    <xsl:variable name="group" 
                  select="key('grouptemperatureInformation', concat(generate-id(ancestor::pos), '|', ../attr[@name = 'temperatureCode'], '|', ../attrQualMany[@name = 'temperature']))/attrGroupMany[@name='temperatureStats']/row" />

Then you could then select the distinct "temperatureStats" elements within this using the second key

  <xsl:apply-templates select="@* | $group[generate-id() = generate-id(key('grouptemperatureStats', concat(generate-id(ancestor::pos), '|', ../../../attr[@name = 'temperatureCode'], '|', ../../../attrQualMany[@name = 'temperature'], '|', attr[@name = 'StatsCode']))[1])]"/> 

Try this XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:key name="grouptemperatureInformation" 
             match="party/pos/attrGroupMany[@name = 'temperatureInformation']/row"
             use="concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature'])"/>

    <xsl:key name="grouptemperatureStats" 
             match="party/pos/attrGroupMany[@name = 'temperatureInformation']/row/attrGroupMany[@name = 'temperatureStats']/row"
             use="concat(generate-id(ancestor::pos), '|', ../../../attr[@name = 'temperatureCode'], '|', ../../../attrQualMany[@name = 'temperature'], '|', attr[@name = 'StatsCode'])"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="attrGroupMany[@name = 'temperatureInformation']">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="row[generate-id() = generate-id(key('grouptemperatureInformation', concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature']))[1])]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="attrGroupMany[@name = 'temperatureStats']">
        <xsl:variable name="group" select="key('grouptemperatureInformation', concat(generate-id(ancestor::pos), '|', ../attr[@name = 'temperatureCode'], '|', ../attrQualMany[@name = 'temperature']))/attrGroupMany[@name='temperatureStats']/row" />
        <xsl:copy>
            <xsl:apply-templates select="@* | $group[generate-id() = generate-id(key('grouptemperatureStats', concat(generate-id(ancestor::pos), '|', ../../../attr[@name = 'temperatureCode'], '|', ../../../attrQualMany[@name = 'temperature'], '|', attr[@name = 'StatsCode']))[1])]"/> 
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 1

Related Questions