How to remove unwanted elements and attributes from an XML file using XSLT

I have an XML file, I want to copy it as is, but I want to filter out some unwanted elements and attributes, for example, the following source file:

<root> <e1 att="test1" att2="test2"> Value</e1> <e2 att="test1" att2="test2"> Value 2 <inner class='i'>inner</inner></e2> <e3 att="test1" att2="test2"> Value 3</e3> </root> 

After removing the filter element ( e3 and att2 ):

 <root> <e1 att="test1" > Value</e1> <e2 att="test1" > Value 2 <inner class='i'>inner</inner></e2> </root> 

Notes:

  • I prefer to use ( for each ) instead of apply-templates , if possible)
  • I have some problems with xsl: element and xsl: attribute , since I could not write the current node name

thanks

+4
source share
2 answers

I know that you prefer to use for-each , but why not use identifier conversion and then override this template with something you don't want to keep?

This style sheet:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="e3|@att2"/> </xsl:stylesheet> 

gives:

 <root> <e1 att="test1"> Value</e1> <e2 att="test1"> Value 2 <inner class="i">inner</inner> </e2> </root> 
+8
source

As @DevNull showed, using identity conversion is much simpler and less verbose. Anyway, here is one possible solution with for-each and without apply-templates at your request:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:template match="/root"> <root> <xsl:for-each select="child::node()"> <xsl:choose> <xsl:when test="position()=last()-1"/> <xsl:otherwise> <xsl:copy> <xsl:copy-of select="@att"/> <xsl:copy-of select="child::node()"/> </xsl:copy> </xsl:otherwise> </xsl:choose> </xsl:for-each> </root> </xsl:template> 


A Note About Using Identity Conversion

If your situation really looks like this, I mean the unknown element name, @DevNull will not work, and you will need something more general, like this:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="root/child::node()[position()=last()]|@att2"/> </xsl:stylesheet> 

This solution will work even with the latest elements of e4 or e1000 .

+1
source

All Articles