我想知道:
之间是否有任何区别<xsl:template match="/*">
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
和
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
答案 0 :(得分:2)
至少有一个区别。鉴于以下输入:
<root xmlns="htpp://www.example.com/my">my text</root>
这个模板:
<xsl:template match="/*">
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
将产生:
<root>my text</root>
而xsl:copy
将复制保留其名称空间的元素:
<root xmlns="htpp://www.example.com/my">my text</root>
修改强>
回应@parakmiakos的评论:
给出以下输入:
<my:root xmlns:my="htpp://www.example.com/my">my text</my:root>
此模板*:
<xsl:template match="/*">
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
将产生:
<my:root xmlns:my="htpp://www.example.com/my">my text</my:root>
(*),前提是在样式表中声明了“my”前缀。
此模板:
<xsl:template match="/*">
<xsl:element name="{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
将产生:
<root>my text</root>
和这一个:
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
将返回:
<my:root xmlns:my="htpp://www.example.com/my">my text</my:root>
与第一个相同(但不必声明前缀)。
答案 1 :(得分:1)
xsl:element
元素生成一个新的元素节点。
xsl:copy
将上下文项复制到输出序列。但是,所述上下文项不必是元素节点。在你的情况下:
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
上下文项确实是一个元素。这会产生以下后果:
xsl:copy
还复制元素的命名空间(如果有的话)xsl:copy
内的可选序列构造函数。在您的示例中,序列构造函数为<xsl:apply-templates/>
摘要:xsl:copy
可以复制任何类型的节点(原子值,文档,元素,文本,属性,处理指令,注释,命名空间),而xsl:element
完全能够生成元素节点。
用法:使用xsl:copy
有效地将节点从输入XML复制到输出序列。仅当元素名称为动态时才使用xsl:element
,即事先未知。
另外,使用XSLT 2.0,您可以使用属性copy-namespaces
和inherit-namespaces
明确控制名称空间的处理。
答案 2 :(得分:1)
当您在作用域中具有名称空间声明(除了要复制的元素的名称空间)时,差别很明显。使用<xsl:copy>
将复制任何范围内的命名空间节点,而使用<xsl:element>
则不会。所以给出了
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<foo/>
</root>
的样式表
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates select="*/*" />
</xsl:template>
<xsl:template match="foo">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
您将获得
的输出<?xml version="1.0"?>
<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
因为<xsl:copy>
已从input元素复制了范围内的命名空间节点。而如果你使用
<xsl:template match="foo">
<xsl:element name="{name()}" namespace="{namespace-uri()}"/>
</xsl:template>
你会得到
<?xml version="1.0"?>
<foo/>
作为Matthias points out,在XSLT 2.0中,您可以说<xsl:copy copy-namespaces="no">
来禁止复制范围内命名空间 - 对于元素节点,<xsl:copy copy-namespaces="no">
具有与{{1}相同的效果}