XSLT实现复制元素所有子节点时排除指定子元素
问题根因
你写的三个匹配<role>节点的空模板本身没有语法错误,不生效的核心原因是使用了<xsl:copy-of select="staff"/>指令。xsl:copy-of是深拷贝指令,会将选中的staff节点连同其所有属性、子节点、后代节点原封不动直接写入输出,完全绕过XSLT的模板匹配流程,导致你写的过滤逻辑根本没有执行机会。
正确实现代码
把xsl:copy-of替换为xsl:apply-templates,让模板匹配规则正常生效,同时补充通用身份拷贝模板复制所有不需要过滤的节点、属性、文本内容,完整代码如下:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <!-- 身份模板:默认复制所有节点、属性、文本内容 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 空模板匹配role节点:匹配到后不生成任何输出,实现过滤效果 --> <xsl:template match="role"/> <!-- 匹配company节点,直接处理其下所有staff子节点 --> <xsl:template match="/company"> <xsl:apply-templates select="staff"/> </xsl:template> </xsl:stylesheet>
运行上述代码后,输出结果和你给出的预期效果完全一致:所有<staff>节点保留原有属性和<name>子元素,所有<role>元素被排除。
注:上述代码输出三个平级的
<staff>节点,如果你需要符合XML规范的单根结构,只需要在匹配/company的模板中用根标签包裹<xsl:apply-templates select="staff"/>即可,示例:<xsl:template match="/company"> <staffList> <xsl:apply-templates select="staff"/> </staffList> </xsl:template>
扩展说明
这套写法是XSLT中过滤指定节点的通用方案:身份模板负责默认全量复制,你只需要为所有需要排除的节点编写空模板即可,比如后续需要额外排除<name>元素,只需要新增一行<xsl:template match="name"/>。
内容的提问来源于stack exchange,提问作者tm1701
相关产品推荐
相关产品推荐

