xslt strip node tree based on attribute
I would like to use xslt to transform an xml file into an almost identical xml file, but strip out nodes based on an attribute. If a node has an attribute, its children and it are not copied to the output file. For instance I want to strip nodes from the following xml file that have a "healthy" attribute of "not_really"
this is the xml to be transformed
<diet>
<breakfast healthy="very">
<item name="toast" />
<item name="juice" />
</breakfast>
<lunch healthy="ofcourse">
<item name="sandwich" />
<item name="apple" />
<item name="chocolate_bar" healthy="not_really" />
<other_info>lunch is great</other_info>
</lunch>
<afternoon_snack healthy="not_really" >
<item name="crisps"/>
</afternoon_snack>
<some_other_info>
<otherInfo>important info</otherInfo>
</some_other_info>
</diet>
this is the desired output
<?xml version="1.0" encoding="utf-8" ?>
<di开发者_StackOverflow社区et>
<breakfast healthy="very">
<item name="toast" />
<item name="juice" />
</breakfast>
<lunch healthy="ofcourse">
<item name="sandwich" />
<item name="apple" />
<other_info>lunch is great</other_info>
</lunch>
<some_other_info>
<otherInfo>important info</otherInfo>
</some_other_info>
</diet>
this is what I have tried (without sucess:)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()[@healthy=not_really]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Two small issues:
- The value
not_really
should be in quotes, to denote that it is a text value. Otherwise, it will evaluate it as looking for an element named "not_really". - Your apply-templates is selecting the nodes who's
@healthy
value is "not_really", you want the opposite.
Applied fixes to your stylesheet:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()[not(@healthy='not_really')]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Alternatively, you could just create an empty template for the elements that have @healthy='not_really'
:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@healthy='not_really']"/>
</xsl:stylesheet>
精彩评论