Search code examples
xsltxslt-grouping

Remove Duplicate Node of second element using XSLT


I don't have much knowledge on xslt . I am trying to remove some duplicate node from my input xml but the nodes are not exactly duplicate . The PremiseId value is duplicate but the latitude, Longitude, XCoordinate and YCoordinate values are different. If we get such data in our Input xml then we need to pick only that occurrence of XML node which has the latitude, Longitude values . Currently my xslt is only picking up the first occurrence of duplicate PremiseId.

Input XML :-

<CoordinateCollectionRes
    xmlns="http://www.nexteraenergy.org/RetrieveCoordinateResponseSchema"
    xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<ResponseParameter>
        <PremiseId>42210111</PremiseId>
        <Latitude>-80.81082</Latitude>
        <Longitude>28.58942</Longitude>
        <Xcoordinate>3913026</Xcoordinate>
        <Ycoordinate>-42817728</Ycoordinate>
    </ResponseParameter>
    <ResponseParameter>
        <PremiseId>59087449</PremiseId>
        <Latitude/>
        <Longitude/>
        <Xcoordinate>0.0</Xcoordinate>
        <Ycoordinate>0.0</Ycoordinate>
    </ResponseParameter>
    <ResponseParameter>
        <PremiseId>60476616</PremiseId>
        <Latitude/>
        <Longitude/>
        <Xcoordinate>0.0</Xcoordinate>
        <Ycoordinate>0.0</Ycoordinate>
    </ResponseParameter>
    <ResponseParameter>
        <PremiseId>60476616</PremiseId>
        <Latitude>-87.36536</Latitude>
        <Longitude>30.391645</Longitude>
        <Xcoordinate>1556955</Xcoordinate>
        <Ycoordinate>-41998772</Ycoordinate>
    </ResponseParameter>
</CoordinateCollectionRes>

XSLT :-

<?xml version="1.0" encoding="windows-1252" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:ns1="http://www.nexteraenergy.org/RetrieveCoordinateResponseSchema">
  <xsl:template match="/">
    <CoordinateCollectionRes xmlns="http://www.nexteraenergy.org/RetrieveCoordinateResponseSchema">
    <xsl:for-each-group select="/ns1:CoordinateCollectionRes/ns1:ResponseParameter" group-by="./ns1:PremiseId">
        <xsl:copy-of select=".[./ns1:PremiseId=current-grouping-key()]"/>
    </xsl:for-each-group>
  </CoordinateCollectionRes>
  </xsl:template>
</xsl:stylesheet>

Output XML:-

<CoordinateCollectionRes    xmlns:ns1="http://www.nexteraenergy.org/RetrieveCoordinateResponseSchema" xmlns="http://www.nexteraenergy.org/RetrieveCoordinateResponseSchema">
<ResponseParameter>
<PremiseId>42210111</PremiseId>
<Latitude>-80.81082</Latitude>
<Longitude>28.58942</Longitude>
<Xcoordinate>3913026</Xcoordinate>
<Ycoordinate>-42817728</Ycoordinate>
</ResponseParameter>
<ResponseParameter>
<PremiseId>59087449</PremiseId>
<Latitude/>
<Longitude/>
<Xcoordinate>0.0</Xcoordinate>
<Ycoordinate>0.0</Ycoordinate>
</ResponseParameter>
<ResponseParameter>
<PremiseId>60476616</PremiseId>
<Latitude/>
<Longitude/>
<Xcoordinate>0.0</Xcoordinate>
<Ycoordinate>0.0</Ycoordinate>
</ResponseParameter>
</CoordinateCollectionRes>

Expected Output XML :-

<CoordinateCollectionRes    xmlns:ns1="http://www.nexteraenergy.org/RetrieveCoordinateResponseSchema" xmlns="http://www.nexteraenergy.org/RetrieveCoordinateResponseSchema">
<ResponseParameter>
<PremiseId>42210111</PremiseId>
<Latitude>-80.81082</Latitude>
<Longitude>28.58942</Longitude>
<Xcoordinate>3913026</Xcoordinate>
<Ycoordinate>-42817728</Ycoordinate>
</ResponseParameter>
<ResponseParameter>
<PremiseId>59087449</PremiseId>
<Latitude/>
<Longitude/>
<Xcoordinate>0.0</Xcoordinate>
<Ycoordinate>0.0</Ycoordinate>
</ResponseParameter>
<ResponseParameter>
        <PremiseId>60476616</PremiseId>
        <Latitude>-87.36536</Latitude>
        <Longitude>30.391645</Longitude>
        <Xcoordinate>1556955</Xcoordinate>
        <Ycoordinate>-41998772</Ycoordinate>
    </ResponseParameter>
</CoordinateCollectionRes>

Solution

  • How about:

    XSLT 2.0

    <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.nexteraenergy.org/RetrieveCoordinateResponseSchema"
    xpath-default-namespace="http://www.nexteraenergy.org/RetrieveCoordinateResponseSchema">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/CoordinateCollectionRes">
        <CoordinateCollectionRes>
            <xsl:for-each-group select="ResponseParameter" group-by="PremiseId">
                <xsl:copy-of select="(current-group()[string(Latitude|Latitutde)], current-group())[1]" copy-namespaces="no"/>
            </xsl:for-each-group>
        </CoordinateCollectionRes>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Demo: https://xsltfiddle.liberty-development.net/93dFepY