You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT 1.0:如何仅复制含值或后代含值的元素

过滤XML中无有效内容的元素(自身及后代均无值)

现有如下XML文档:

<?xml version="1.0" encoding="utf-8"?>
<Products>
    <Product>
        <Sku />
        <Suppliers>
            <Supplier>
                <Name />
            </Supplier>
        </Suppliers>
        <Priority>1</Priority>
    </Product>
    <Product>
        <Sku>123</Sku>
        <Suppliers>            
            <Supplier>Jon</Supplier>
        </Suppliers>
        <Priority>3</Priority>
        <e />
    </Product>
</Products>

需要通过XSLT转换,仅输出自身含值或后代元素含值的节点。当前使用的过滤模板通过match="*[not(node())]"仅能过滤无后代的空元素,无法处理包含空后代的元素(比如示例中的<Suppliers>和<Supplier>):

<xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>        
    </xsl:template>
    
    <!-- When matching empty: do nothing -->        
    <xsl:template match="*[not(node())]">
        <xsl:comment>filtering <xsl:value-of select="local-name()"/></xsl:comment>
    </xsl:template>    

当前输出(含调试注释)

<?xml version="1.0" encoding="utf-8"?><Products>
    <Product>
        <!--filtering Sku-->
        <Suppliers>
            <Supplier>
                <!--filtering Name-->
            </Supplier>
        </Suppliers>
        <Priority>1</Priority>
    </Product>
    <Product>
        <Sku>123</Sku>
        <Suppliers>            
            <Supplier>Jon</Supplier>
        </Suppliers>
        <Priority>3</Priority>
        <!--filtering e-->
    </Product>
</Products>

期望输出(无注释)

<?xml version="1.0" encoding="utf-8"?><Products>
    <Product>
        <Priority>1</Priority>
    </Product>
    <Product>
        <Sku>123</Sku>
        <Suppliers>            
            <Supplier>Jon</Supplier>
        </Suppliers>
        <Priority>3</Priority>
    </Product>
</Products>

解决方案

核心思路是:判断元素自身及所有后代是否包含有效内容(非空白文本),如果完全没有则过滤该元素。修改后的XSLT如下:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- 身份模板:默认复制所有节点和属性 -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <!-- 过滤自身及后代均无有效内容的元素 -->
    <xsl:template match="*[not(normalize-space(.))]"/>
</xsl:stylesheet>

说明:

  • normalize-space(.)会将元素自身及所有后代的文本内容合并,去除首尾空白并压缩中间空白。如果结果为空,说明该元素及其所有后代都没有非空白的有效文本。
  • 匹配这类元素的模板不执行任何复制操作,直接过滤掉它们,最终只保留包含有效内容的元素及其父元素(父元素如果有有效后代则会被保留)。

这个方案会递归判断元素的所有后代,自动过滤掉所有空的元素分支,完全符合期望输出的要求。


内容的提问来源于stack exchange,提问作者Jonny Hotchkiss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 03:01:00