XSLT中的子级为空时,递归删除节点

时间:2018-11-21 18:00:16

标签: xml xslt

我是使用xsl的新手,我不确定如何删除特定的父节点及其所有子节点(如果全部为空)。我认为link中显示的答案是我所需要的,但是我不确定如何将其应用于特定节点而不是整个样式表。

使用该问题中的内容,我将其扩展了...

<farm>
    <foo>
    <bar>
        <baz/>
    </bar>
    <quux>  </quux>
    <quuux>Actual content</quuux>
    </foo>
    <sounds>
        <moo>
            <meow>
                <buzz></buzz>
            </meow>
        </moo>
        <birds>
            <cluck>  </cluck>
            <quack></quack>
        </birds>
    </sounds>
</farm>

我如何消除<sounds>及其所有子级(如果它们全部为空),而又留下诸如foo,bar和baz之类的空节点。我正在生成的xml的需求即使它们为空白也需要具有某些标记,但是如果它们为空白,则需要将其删除。

走得更远,如果我拥有的是...

<farm>
    <foo>
    <bar>
        <baz/>
    </bar>
    <quux>  </quux>
    <quuux>Actual content</quuux>
    </foo>
    <sounds>
        <moo>
            <meow>
                <buzz>"zzzz"</buzz>
            </meow>
        </moo>
        <birds>
            <cluck>  </cluck>
            <quack></quack>
        </birds>     <!-- Fixed by edit -->
    </sounds>
</farm>

在此示例中,<sounds>, <moo>, <meow><buzz>将需要保留,因为<buzz>具有值,但是<birds>及其子项将被删除。

在我看来,这是如此复杂,我不确定最简单的方法是什么。

非常感谢您的指导,因为我走了这么多圈子感到头晕目眩!

2 个答案:

答案 0 :(得分:1)

如果您的处理器不支持XSLT 3.0,这是XSLT 1.0选项...

<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="*[ancestor-or-self::sounds][not(string())]"/>

</xsl:stylesheet>

例如#1的小提琴:http://xsltfiddle.liberty-development.net/jyH9rNp

以小提琴为例#2:http://xsltfiddle.liberty-development.net/jyH9rNp/1

答案 1 :(得分:0)

假设XSLT 3(受Saxon 9.8和9.9的Java平台以及受Saxon 9.8的.NET平台支持,以及Altova 2017/2018/2019也受支持),则可以将xsl:where-populated与{{1}一起使用} xsl:next-match和其他任何后代元素以及其余的身份转换;另外,您将需要去除空格,否则sounds不会被删除:

<cluck>  </cluck>

https://xsltfiddle.liberty-development.net/gWmuiKn/0是您的第一个输入,而https://xsltfiddle.liberty-development.net/gWmuiKn/1是您的第二个输入。