0

Input XML with Multiple same key value:

<ns2:enumCollection>
    <ns3:item>
        <ns3:key>000</ns3:key>
        <ns3:value>GRS Tracker00CA1</ns3:value>
    </ns3:item>
    <ns3:item>
        <ns3:key>000</ns3:key>
        <ns3:value>GRS Tracker00CA1</ns3:value>
    </ns3:item>
    <ns3:item>
        <ns3:key>001</ns3:key>
        <ns3:value>GRS Tracker00CA2</ns3:value>
    </ns3:item>                             
</ns2:enumCollection>

Expected Output Result

<ns2:enumCollection>
    <ns3:item>
        <ns3:key>000</ns3:key>
        <ns3:value>GRS Tracker00CA1</ns3:value>
    </ns3:item>
    <ns3:item>
        <ns3:key>001</ns3:key>
        <ns3:value>GRS Tracker00CA2</ns3:value>
    </ns3:item>                             
</ns2:enumCollection>

Need Help on this Transformation. I am trying to use xsl:Key function but not able to transform successfully.

Francesco Irrera
  • 445
  • 4
  • 21

1 Answers1

1

The first thing to note is that your input XML has namespace prefixes, but there are no declarations for them, which is not allowed. I am assuming your actual XML does have them though! For the purposes of this answer though, I am going to make up some namespaces

<ns2:enumCollection xmlns:ns2="ns2" xmlns:ns3="ns3">
    <ns3:item>
        <ns3:key>000</ns3:key>
        <ns3:value>GRS Tracker00CA1</ns3:value>
    </ns3:item>
    <ns3:item>
        <ns3:key>000</ns3:key>
        <ns3:value>GRS Tracker00CA1</ns3:value>
    </ns3:item>
    <ns3:item>
        <ns3:key>001</ns3:key>
        <ns3:value>GRS Tracker00CA2</ns3:value>
    </ns3:item>                             
</ns2:enumCollection>

To get unique values, you can make use of a technique called Muenchian grouping as that involves getting the unique values initially, but in your case you are discarding the rest of the 'group'.

If you are grouping items by key, then your XML should actually look like this

<xsl:key name="element-key" match="ns3:item" use="ns3:key" /> 

Then, to get your "distinct" values, you would do this to get the item for the first occurrence of each key

Try this XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="ns2" xmlns:ns3="ns3">
    <xsl:output method="xml" indent="yes"/>
    <xsl:key name="element-key" match="ns3:item" use="ns3:key" /> 

    <xsl:template match="ns2:enumCollection">
       <xsl:copy>
          <xsl:apply-templates select="ns3:item[generate-id() = generate-id(key('element-key', ns3:key)[1])]"/>
        </xsl:copy>
    </xsl:template>

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

Alternatively, you could have a template to 'discard' the elements that aren't first in each group

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="ns2" xmlns:ns3="ns3">
    <xsl:output method="xml" indent="yes"/>
    <xsl:key name="element-key" match="ns3:item" use="ns3:key" /> 

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

    <xsl:template match="ns3:item[generate-id() != generate-id(key('element-key', ns3:key)[1])]" />
</xsl:stylesheet>

Both of these output the following

<ns2:enumCollection xmlns:ns2="ns2" xmlns:ns3="ns3">
    <ns3:item>
        <ns3:key>000</ns3:key>
        <ns3:value>GRS Tracker00CA1</ns3:value>
    </ns3:item>
    <ns3:item>
        <ns3:key>001</ns3:key>
        <ns3:value>GRS Tracker00CA2</ns3:value>
    </ns3:item>
</ns2:enumCollection>
Tim C
  • 70,053
  • 14
  • 74
  • 93
  • Hi Tim, need one more help if we want to keep the items with unique combination of key and value, how can we achive it – Subhodeep Ray Dec 12 '14 at 10:41
  • You can do something like `` to get all the items in the group with the same key. But it's probably best to ask a whole new question about this, as it will be hard to give a precise answer using just comments. Thanks! – Tim C Dec 12 '14 at 10:47
  • if you can add comments to the below post https://stackoverflow.com/questions/27442729/remove-the-duplicate-node-based-on-unique-combination-in-xslt – Subhodeep Ray Dec 12 '14 at 11:31
  • Sorry, I initially misunderstood what you were asking. It is actually quite straight-forward to group on key and value. I've answered your new question to show this. – Tim C Dec 12 '14 at 11:43