xmlxsltxml-parsing

Remove few nodes in the xml with a match text in the sibling nodes using xslt


Trying to remove few nodes in the xml with a matching text in the sibling nodes using xslt

my xml looks like below

    <?xml version="1.0" encoding="UTF-8"?>
    <root xmlns:map="http://www.w3.org/2005/xpath-functions/map">
    <row>
        <Keep_Name>Africa</Keep_Name>
    </row>
    <row>
        <Keep_Name>USA</Keep_Name>
    </row>
    <row>
        <Keep_Name>Mexico</Keep_Name>
    </row>
    <row>
        <Keep_Name>Canada</Keep_Name>
    </row>
    <row>
        <Keep_Name>Malaysia</Keep_Name>
    </row>
    <row>
        <Remove_Name>Africa</Remove_Name>
    </row>
    <row>
        <Remove_Name>Mexico</Remove_Name>
    </row>
    <row>
        <Remove_Name>Srilanka</Remove_Name>
    </row>
    <row>
        <Keep_Name>Bangladesh</Keep_Name>
    </row>
    </root>`

and the output i need is below

   
    `<?xml version="1.0" encoding="UTF-8"?>
     <root >
     <row>
      <Keep_Name>USA</Keep_Name>
     </row>
     <row>
      <Keep_Name>Canada</Keep_Name>
     </row>
     <row>
      <Keep_Name>Malaysia</Keep_Name>
     </row>
     <row>
      <Keep_Name>Bangladesh</Keep_Name>
     </row>
     </root>

` tried below xslt but not working properly. I want these to remove Remove_Name nodes along with Keep_Name nodes of the same value to be removed altogether from the output

    `<xsl:stylesheet version="2.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:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
     </xsl:template>
    
    
     <xsl:template match="row[.=preceding-sibling::row/.]"/>
     </xsl:stylesheet>`

Tried this above xslt but it is not working as expected.

Please help me to remove these Remove_Name and Keep_Name nodes in the output only if their text is matching.`


Solution

  • If I understand the required logic correctly, it could be implemented as:

    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:key name="row-by-name" match="row" use="Remove_Name" />
    
    <xsl:template match="/root">
        <xsl:copy>
            <xsl:copy-of select="row[Keep_Name][not(key('row-by-name', Keep_Name))]"/>
        </xsl:copy>
    </xsl:template>
        
    </xsl:stylesheet>
    

    This copies every row with a Keep_Name that doesn't have a matching row with Remove_Name.