xslt - 递归空节点清理

时间:2016-02-15 15:12:08

标签: xml xslt

我正在尝试使用任意元素名称清理文件,如下所示:

<root>
    <nodeone>
        <subnode blah="1" blah2="abc" />
    </nodeone>
    <nodeone>
        <subnode>with other stuff</subnode>
    </nodeone>
    <nodeone>
        <subnode />
    </nodeone>
</root>

进入一个看起来像的文件:

<root>
    <nodeone>
        <subnode blah="1" blah2="abc" />
    </nodeone>
    <nodeone>
        <subnode>with other stuff</subnode>
    </nodeone>
</root>

您可以看到所有具有空子项的“nodeone”都消失了,但保留了内容或非空属性的任何<nodeone>

我目前对解决方案的尝试是:

<?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" />
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[not(normalize-space()) and not(@*)]"/>

</xsl:stylesheet>

这将删除任何内部空白内容并保留属性的节点,但也会从输出中删除<nodeone />文本,这不是所需的结果。

2 个答案:

答案 0 :(得分:2)

如果您想要通用解决方案,请尝试使用此模板

<xsl:template match="*[not(normalize-space()) and not(.//@*)]"/>

这里.//@*将检查当前元素(被匹配)和所有后代元素的属性。

答案 1 :(得分:0)

您要匹配具有任何名称且既没有文字内容也没有属性的元素。因此,这也符合您的<nodeone>元素。试试这个:

<?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="nodeone[*[not(normalize-space())][not(@*)]]"/>
</xsl:stylesheet>