Reputation: 5575
I have XML file , I want to copy it as it is , but I want to filter some unwanted elements and attributes , for example the following is the original 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 the filtration ( e3 element and att2 attribute have been removed ) :
<root>
<e1 att="test1" > Value</e1>
<e2 att="test1" > Value 2 <inner class='i'>inner</inner></e2>
</root>
Notes:
Thanks
Upvotes: 4
Views: 18938
Reputation: 52858
I know you'd prefer to use for-each
, but why not use an identity transform and then override that template with what you don't want to keep?
This stylesheet:
<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>
produces:
<root>
<e1 att="test1"> Value</e1>
<e2 att="test1"> Value 2 <inner class="i">inner</inner>
</e2>
</root>
Upvotes: 9
Reputation: 24816
As @DevNull has shown you, using the identity transform is much easier and less verbose. Anyway, here is one possible solution with for-each
and without apply-templates
as you requested:
<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>
Note about using identity transform
If your situation is really what it looks like, I mean unknown name of the elements, the @DevNull won't work and you would need somthing 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 last elements e4
or e1000
.
Upvotes: 1