开发者

XSL Ignore Empty Children Recursively

开发者 https://www.devze.com 2022-12-13 22:44 出处:网络
Trying something kind of wacky in cleaning up some verbose XML, which is to remove all empty nodes recursively.

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() = '']"/>
0

精彩评论

暂无评论...
验证码 换一张
取 消