XSLT Identity Transform 不复制所有属性
XSLT Identity Transform doesn't copy all attributes
我有以下 XSL 转换代码:
<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:stylesheet>
这是身份转换的标准样本。对于大多数情况,它工作得恰到好处。但是当它没有正确复制时,我能够找到一个案例。对于以下 XML 代码:
<c xmlns:x="x">
<a xmlns:x="x"/>
</c>
转换后的 xml 代码如下所示:
<c xmlns:x="x"><a /></c>
如果您从 XML 代码中删除名称空间 xmlns
,它就会开始正常工作。此外,如果您更改第二个参数的名称(离开 xmlns
命名空间),您将进行适当的恒等式转换。我被卡住了,因为我无法解释为什么对这个完全相同的命名空间使用相同的参数会造成这样的麻烦。
顺便说一句,您可以在 https://www.freeformatter.com/xsl-transformer.html 网页上重现这些错误。
本质上,元素声明的命名空间前缀 xmlns:x="x"
与 相同的 命名空间前缀和 URI 作为其父级匹配是多余的。 XSLT 处理消除了这种冗余。两者本质上是相同的 XML 内容。
根据 Namespaces in XML 上的 W3C 规则(强调已添加):
If the attribute name matches PrefixedAttName, then the NCName gives
the namespace prefix, used to associate element and attribute names
with the namespace name in the attribute value in the scope of the
element to which the declaration is attached.
...
An example namespace declaration, which associates the namespace
prefix edi with the namespace name http://ecommerce.org/schema
:
<x xmlns:edi='http://ecommerce.org/schema'>
<!-- the "edi" prefix is bound to http://ecommerce.org/schema
for the "x" element and contents -->
</x>
特别是对于您的用例,x 命名空间前缀已经在 <c>
的范围内定义,因此 <a>
(作为子元素)可以在其内容中的任何位置使用 x
命名空间前缀而无需其他声明。所以你原来的内容:
<c xmlns:x="x">
<a xmlns:x="x"/>
</c>
与 XSLT 输出相同:
<c xmlns:x="x"><a/></c>
或使用 @michael.hor257k 评论中提到的换行符和缩进。
<c xmlns:x="x">
<a/>
</c>
我有以下 XSL 转换代码:
<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:stylesheet>
这是身份转换的标准样本。对于大多数情况,它工作得恰到好处。但是当它没有正确复制时,我能够找到一个案例。对于以下 XML 代码:
<c xmlns:x="x">
<a xmlns:x="x"/>
</c>
转换后的 xml 代码如下所示:
<c xmlns:x="x"><a /></c>
如果您从 XML 代码中删除名称空间 xmlns
,它就会开始正常工作。此外,如果您更改第二个参数的名称(离开 xmlns
命名空间),您将进行适当的恒等式转换。我被卡住了,因为我无法解释为什么对这个完全相同的命名空间使用相同的参数会造成这样的麻烦。
顺便说一句,您可以在 https://www.freeformatter.com/xsl-transformer.html 网页上重现这些错误。
本质上,元素声明的命名空间前缀 xmlns:x="x"
与 相同的 命名空间前缀和 URI 作为其父级匹配是多余的。 XSLT 处理消除了这种冗余。两者本质上是相同的 XML 内容。
根据 Namespaces in XML 上的 W3C 规则(强调已添加):
If the attribute name matches PrefixedAttName, then the NCName gives the namespace prefix, used to associate element and attribute names with the namespace name in the attribute value in the scope of the element to which the declaration is attached.
...
An example namespace declaration, which associates the namespace prefix edi with the namespace namehttp://ecommerce.org/schema
:<x xmlns:edi='http://ecommerce.org/schema'> <!-- the "edi" prefix is bound to http://ecommerce.org/schema for the "x" element and contents --> </x>
特别是对于您的用例,x 命名空间前缀已经在 <c>
的范围内定义,因此 <a>
(作为子元素)可以在其内容中的任何位置使用 x
命名空间前缀而无需其他声明。所以你原来的内容:
<c xmlns:x="x">
<a xmlns:x="x"/>
</c>
与 XSLT 输出相同:
<c xmlns:x="x"><a/></c>
或使用 @michael.hor257k 评论中提到的换行符和缩进。
<c xmlns:x="x">
<a/>
</c>