【问题标题】:XSLT Identity Transform doesn't copy all attributesXSLT 身份转换不会复制所有属性
【发布时间】:2019-07-15 18:45:52
【问题描述】:

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

【问题讨论】:

  • 这两个结果在语义上是相同的。缩进取决于您的处理器 - 例如,请参见此处的不同结果:xsltfiddle.liberty-development.net/94rmq75 您可以使用&lt;xsl:output indent="yes"/&gt; 和/或xsl:strip-spacexsl:preserve-space 指令在一定程度上控制缩进。

标签: xml xslt xslt-1.0


【解决方案1】:

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

根据Namespaces in XML 上的 W3C 规则(已添加重点):

如果属性名称与 PrefixedAttName 匹配,则 NCName 给出 命名空间前缀,用于关联元素和属性名称 名称空间名称在属性值 的范围内 声明所附加的元素
...
一个示例命名空间声明,它关联命名空间 以命名空间名称为 edi 前缀 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 命名空间前缀已经在&lt;c&gt; 的范围内定义,因此&lt;a&gt;(作为子元素)可以在任何地方使用x 命名空间前缀它的内容没有另一个声明。所以你的原创内容:

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

与 XSLT 输出相同:

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

或者@michael.hor257k 在 cmets 中提到的换行和缩进。

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

【讨论】:

  • 谢谢!我因此完全陷入困境。
  • 从技术上讲,甚至不是 XSLT 处理器删除了多余的名称空间声明:它是处理器/解析器构造 XDM 输入到 XSLT 处理器。 XSLT 被定义为对数据模型 XDM 进行操作,它无法表示有关冗余名称空间声明的信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多