Trying something kind of wacky in cleaning up some verbose XML, which is to remove all empty nodes recursively.
For this purpose, I consider a node to be "empty" if it has (a) no child nodes, (b) whitespace-only content, (c) only "empty" child nodes. That is, I cons开发者_StackOverflowider the following to be "empty" because all of the leaves are empty/whitespace-only nodes:
<foo>
<bar>
<baz/>
</bar>
<quux> </quux>
</foo>
I tried using <xsl:if test="child::node()">
in my templates, but that didn't seem to work. It's entirely possible the answer is "walk the tree yourself, silly", but it seems like the sort of thing XSL should be able to do?
I would expect
<foo>
<bar>
<baz/>
</bar>
<quux> </quux>
<quuux>Actual content</quuux>
</foo>
to come back as
<foo>
<quuux>Actual content</quuux>
</foo>
with this filter I have in mind.
The reason why child::node()
didn't work for you was because you do have child nodes there - they're whitespace text nodes. Instead, try something like normalize-space() != ''
. You probably don't want an if
there, either - put it in match
instead:
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[normalize-space() = '']"/>
Pavel's answer is correct. Two small mistakes though: you need to close the xsl:copy
node, and apply:templates
uses select
instead of match
. This would be the final version:
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[normalize-space() = '']"/>
精彩评论