xsl:copy仅浅复制当前节点本身,需显式调用apply-templates复制子节点、属性或命名空间;xsl:copy-of则深复制select指定的整个节点集,含所有子节点、属性、命名空间及文本内容。

如果您在使用XSLT处理XML文档时需要复制节点,但对xsl:copy和xsl:copy-of的行为差异感到困惑,则可能是由于二者在节点处理范围、上下文继承及属性/命名空间处理方式上存在本质区别。以下是针对该问题的详细说明与操作对比:
一、xsl:copy的基本行为与操作步骤
xsl:copy仅复制当前匹配节点本身(即“浅复制”),不自动复制其子节点、属性或命名空间节点;是否复制这些内容取决于后续是否显式调用xsl:apply-templates或xsl:copy-of。它保留原始节点的名称、类型、命名空间前缀绑定,但不继承父上下文中的默认命名空间声明。
1、在模板规则中编写xsl:copy元素,例如:
2、若需同时复制属性和命名空间节点,必须在xsl:copy内部添加xsl:apply-templates select="@*|namespace::*"。
3、若需复制子元素和文本节点,需额外添加xsl:apply-templates select="node()"。
二、xsl:copy-of的基本行为与操作步骤
xsl:copy-of执行“深复制”,直接生成指定节点或节点集的完整副本,包括所有子节点、属性、命名空间节点及文本内容;它不触发模板匹配机制,也不受当前模板模式影响,输出结果完全由select表达式决定。
1、使用xsl:copy-of时必须提供select属性,例如:
2、select可指向单个节点、节点集或结果树片段(RTF),复制结果将按原结构展开为最终输出树的一部分。
3、当select返回空序列时,xsl:copy-of不产生任何输出,且不会报错。
三、命名空间处理差异的操作验证
xsl:copy在复制元素时会重新评估该元素在源文档中的命名空间绑定,但不会自动复制未在源中显式声明的默认命名空间;而xsl:copy-of则严格按节点实际存储的命名空间信息进行复制,包括隐式继承的默认命名空间声明。
1、构造一个带默认命名空间的XML元素,如:
2、对root元素应用xsl:copy后,若未显式处理namespace::*,输出中可能丢失默认命名空间声明。
3、对同一root元素应用xsl:copy-of select=".",则输出中完整保留xmlns="http://example.com"声明及所有嵌套关系。
四、属性节点复制方式的操作对比
xsl:copy默认不复制任何属性,即使属性存在于当前节点上;xsl:copy-of则只要属性属于select所指节点的一部分,就会被一并复制。
1、定义源节点:
2、仅用xsl:copy处理item节点,输出为:
3、改用xsl:copy-of select=".",输出为:
五、上下文节点类型敏感性的操作检查
xsl:copy可作用于任意XSLT节点类型(元素、属性、文本、注释、处理指令、命名空间节点),但xsl:copy-of的select表达式若指向属性节点或命名空间节点,在XSLT 1.0中会导致运行时错误;XSLT 2.0+允许复制所有节点类型。
1、尝试在XSLT 1.0样式表中编写:
2、相同表达式在XSLT 2.0及以上版本中合法,且输出为纯文本值“123”而非属性节点。
3、使用xsl:copy处理@id节点,在所有XSLT版本中均合法,并生成一个属性节点而非字符串值。










