Search code examples
xmlxsltxslt-2.0

XSLT :How to remove duplicate Tag in XML


We are getting duplicate tag in this Input XML. we wanted to remove this duplication using XSLT2.0 template Instruction.

Input XML :

<?xml version="1.0" encoding="UTF-8"?>
<SalesOrders xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="SDOC.XSD">
   <Orders>
      <OrderHeader>
         <CustomerPoNumber>AB-54354</CustomerPoNumber>
      </OrderHeader>
      <OrderDetails>
         <CommentLine>
            <Comment>Ensure saddle is color coded</Comment>
            <OrderLineID>OR-1810127</OrderLineID>
         </CommentLine>
         <CommentLine>
            <Comment>EDI-001</Comment>
            <OrderLineID>OR-1810128</OrderLineID>
         </CommentLine>
         <StockLine>
            <CustomerPoLine>9999</CustomerPoLine>
            <StockCode>ABSH-SMH-12OZ-01</StockCode>
            <StockDescription>SMH ABS BALANCE SHAMPOO 12OZ</StockDescription>
            <OrderQty>1.0</OrderQty>
         </StockLine>
         <CommentLine>
            <Comment>This is for test purpose</Comment>
            <OrderLineID>OR-1810124</OrderLineID>
         </CommentLine>
         <CommentLine>
            <Comment>EDI-SAVE</Comment>
            <OrderLineID>OR-1810125</OrderLineID>
         </CommentLine>
         <CommentLine>
            <Comment>Ensure saddle is color coded</Comment>
            <OrderLineID>OR-1810127</OrderLineID>
         </CommentLine>
      </OrderDetails>
   </Orders>
</SalesOrders>

We Tried following XSLT on it:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="xml" encoding="Windows-1252" indent="yes" />
   <xsl:template match="@*|node()">
      <xsl:copy copy-namespaces="no">
         <xsl:apply-templates select="@*|node()" />
      </xsl:copy>
   </xsl:template>
   <xsl:template match="StockLine[not(StockCodeDescription) and not (OrderQty) and not(Price)]">
      <CommentLine>
         <Comment>
            <xsl:value-of select="StockCode" />
         </Comment>
         <xsl:copy-of select="OrderLineID" />
      </CommentLine>
   </xsl:template>
   <xsl:template match="CommentLine[OrderLineID = preceding-sibling::StockLine/OrderLineID and not(Comment)]" />
</xsl:stylesheet>

Expected Output XML:

<?xml version="1.0" encoding="UTF-8"?>
<SalesOrders xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="SDOC.XSD">
   <Orders>
      <OrderHeader>
         <CustomerPoNumber>AB-54354</CustomerPoNumber>
      </OrderHeader>
      <OrderDetails>
         <CommentLine>
            <Comment>Ensure saddle is color coded</Comment>
            <OrderLineID>OR-1810127</OrderLineID>
         </CommentLine>
         <CommentLine>
            <Comment>EDI-001</Comment>
            <OrderLineID>OR-1810128</OrderLineID>
         </CommentLine>
         <StockLine>
            <CustomerPoLine>9999</CustomerPoLine>
            <StockCode>ABSH-SMH-12OZ-01</StockCode>
            <StockDescription>SMH ABS BALANCE SHAMPOO 12OZ</StockDescription>
            <OrderQty>1.0</OrderQty>
         </StockLine>
         <CommentLine>
            <Comment>This is for test purpose</Comment>
            <OrderLineID>OR-1810124</OrderLineID>
         </CommentLine>
         <CommentLine>
            <Comment>EDI-SAVE</Comment>
            <OrderLineID>OR-1810125</OrderLineID>
         </CommentLine>
      </OrderDetails>
   </Orders>
</SalesOrders>

This element is duplicating inside XML.

<CommentLine>
            <Comment>Ensure saddle is color coded</Comment>  
            <OrderLineID>OR-1810127</OrderLineID>  
          </CommentLine>  

Any help on it would be much appreciated !


Solution

  • If all you want to eliminate is the exact duplicates of CommentLine elements then use

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="xs"
        version="2.0">
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="CommentLine[some $sib in preceding-sibling::CommentLine satisfies deep-equal(., $sib)]"/>
    </xsl:stylesheet>