Ajith
Ajith

Reputation: 3

Removing duplicate elements based on values in XSLT 1.0

I have done more research on removing duplicated elements. Most of place , They used the key functions with defined element name. In my case , I don't have any defined elements. I have tried to modified the examples

Input XML :

<Test>
<Req>
  Test
  <A name="Test">Inp1</A>
  <B>Inp2</B>
  <D>Inp3</D>
</Req>
<Resp>
  <A name="Test222">Inp1</A>
  <A>Out1</A>
  <B>Inp1</B>
  <B>Inp2</B>
  <C>Inp3</C>
</Resp>
</Test>

XSL : (I have tried after referring plenty of examples. )

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:key name="unique" match="/Test" use="*"/>
<xsl:template match="/">
    <xsl:for-each select="key('unique',//*)">
        <xsl:if test="generate-id() = generate-id(key('unique',.)[1])">
            <xsl:copy-of select="."/>
        </xsl:if>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Expected Output :

<Test>
 <Req>
  Test
  <A name="Test">Inp1</A>
  <B>Inp2</B>
  <D>Inp3</D>
</Req>
<Resp>
  <A>Out1</A> 
  <B>Inp1</B> <!-- Inp1 is already available for <A>. Not for <B>. Should not remove this -->
  <C>Inp3</C> <!-- Inp3 is already available for <D>. Not for <C>. Should not remove this -->
</Resp>
</Test>

We have match element name and value. (We have to ignore attributes for this).

NEED SOLUTION ONLY ON XSLT 1.0 or 1.1

Appreciate help on this. Thanks :)

Upvotes: 0

Views: 1727

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116992

Try it this way:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="unique" match="Req/* | Resp/*" use="concat(local-name(), '|', .)"/>

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

<xsl:template match="Req/* | Resp/*">
    <xsl:if test="generate-id() = generate-id(key('unique', concat(local-name(), '|', .))[1])">
        <xsl:copy-of select="."/>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

When applied to your example input:

<Test>
<Req>
  Test
  <A name="Test">Inp1</A>
  <B>Inp2</B>
  <D>Inp3</D>
</Req>
<Resp>
  <A name="Test222">Inp1</A>
  <A>Out1</A>
  <B>Inp1</B>
  <B>Inp2</B>
  <C>Inp3</C>
</Resp>
</Test>

the result is:

<?xml version="1.0" encoding="UTF-8"?>
<Test>
   <Req>
  Test
  <A name="Test">Inp1</A>
      <B>Inp2</B>
      <D>Inp3</D>
   </Req>
   <Resp>
      <A>Out1</A>
      <B>Inp1</B>
      <C>Inp3</C>
   </Resp>
</Test>

Upvotes: 1

Related Questions