XSLT Identity Transform不会复制所有属性

时间:2019-07-15 18:45:52

标签: xml xslt xslt-1.0

我有以下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网页上重现这些错误。

1 个答案:

答案 0 :(得分:3)

本质上,元素的声明的名称空间前缀xmlns:x="x"相同名称空间前缀和URI匹配为其父元素是多余的。 XSLT处理消除了这种冗余。两者本质上是相同的XML内容。

根据Namespaces in XML上的W3C规则(强调):

  

如果属性名称与PrefixedAttName相匹配,则NCName将给出   名称空间前缀,用于关联元素和属性名称   名称空间名称在属性范围中   声明所附的元素。   
...
  命名空间声明示例,它与命名空间相关联   用名称空间名称http://ecommerce.org/schema前缀edi:

<x xmlns:edi='http://ecommerce.org/schema'>
  <!-- the "edi" prefix is bound to http://ecommerce.org/schema
       for the "x" element and contents -->
</x>

具体针对您的用例,在<c>的范围内已经定义了 x 命名空间前缀,因此<a>(作为子元素)可以使用{{1 }}名称空间前缀在其内容中的任何位置都没有其他声明。所以你的原始内容:

x

与XSLT输出相同:

<c xmlns:x="x">
    <a xmlns:x="x"/>
</c>

或者使用@ michael.hor257k的注释中提到的换行符和缩进。

<c xmlns:x="x"><a/></c>