如何控制 XSLT 输出中的命名空间前缀(特别是默认命名空间)?

How do I control namespace prefixes (specifically the default namespace) in XSLT output?

提问人:Norman Gray 提问时间:12/11/2020 更新时间:12/11/2020 访问量:95

问:

在 XSLT 中,有什么方法可以控制输出元素中命名空间前缀的选择?

在我的特殊情况下,我实际上想转换如下所示的输入

<h:html xmlns:h='http://www.w3.org/1999/xhtml'
        xmlns:m='http://www.w3.org/1998/Math/MathML'>
....
<h:p>Equation: <m:math>...</m:math></h:p>

<html xmlns='http://www.w3.org/1999/xhtml'>
....
<p>Equation: <math xmlns='http://www.w3.org/1998/Math/MathML'>...</math></p>

也就是说,身份转换只需更改命名空间前缀,以根据需要对 XHTML 和 MathML 元素使用默认命名空间。

这是纯 XML 工作流末尾的一个整理步骤。以上当然在XML术语中是等价的,因此在XHTML术语中也是等价的,但浏览器似乎并不总是知道这一点(在我不是很系统的测试中,Firefox管理上述两个,在将它们呈现为数学的意义上 - Firefox干得好! – Safari管理第二个但不是第一个,Chrome也不管理;我实际上是针对 EPUB 读者的,但对那里的 XHTML 解析器持悲观态度似乎是明智的)。尝试使用 XSLT 元素不会对输出产生任何影响。XHTML 兼容性指南没有提到命名空间,这令人惊讶。添加 doctype 声明,甚至是提示 application/xhtml+xml 的 hack,似乎对浏览器的行为没有任何影响。<output method='html'/><meta http-equiv=''...>

在 XSLT 1.0 规范中,我看不到任何控制这一点的内容。这里提到的命名空间别名正在解决一个不同的问题;在 XSLT 中使用默认命名空间不会提供任何似乎倾向于采用的提示。其他堆栈交换问题(例如这个或这个)似乎在很大程度上是对 XSLT 和命名空间的误解。我敢肯定,在我漫长的 XSLT 过去的某个时刻,我已经成功地实现了这一点,但即使我做到了,我也无法复活它。libxslt

我非常喜欢 XSLT 1.0 中的解决方案,因为我有可用的工具和经验,可以在 libxslt 和 (Saxon 是一件非常美妙的事情,但我不愿意为可能的许多连续转换支付 Java 启动成本)。当然,这可能是迫使我使用更高版本的原因,如果更高版本确实是唯一可以提供帮助的东西。xsltproc

从(不是很彻底)查看 XSLT 3 规范(例如第 11.1 节),我看不到任何明显解决这个问题的内容。

如果我吠错了树,或者如果已知 EPUB 处理器对命名空间始终更了解,因此我实际上解决了问题的错误部分,我也对这些信息持开放态度。

XSLT 命名空间

评论


答:

1赞 Martin Honnen 12/11/2020 #1

您需要进行转型

<xsl:template match="*">
  <xsl:element name="{local-name()}" namespace="namespace-uri()">
     <xsl:apply-templates select="@* | node()"/>
  </xsl:element>
</xsl:template>

为其余部分设置标识转换模板。

在 XSLT 1 中,您有点依赖 XSLT 处理器及其序列化程序的怜悯来获得所需的输出,但我认为对于上面的模板,即使在 1.0 世界中,您也可以期待一些一致性。

评论

0赞 Norman Gray 12/11/2020
这看起来很有希望,而且在我尝试过的简单情况下确实有效。真正的代码当然比我的问题稍微复杂一些,但我会试一试,然后回到这个答案。
0赞 Norman Gray 12/17/2020
这在实践中确实非常有效,从某种意义上说,这似乎给序列化器提供了足够的提示。序列化器没有完全接受提示(正如你所建议的):不幸的是,在此构造中处理的任何包含 eg 的模板都使用该前缀序列化,而不是默认前缀,此时该前缀仍在范围内。这意味着我不能将 XSLT 元素保留在默认命名空间中,但是......我会活下去。谢谢你,马丁,你让我放心,我没有错过任何东西。<h:p xmlns:h='http://www.w3.org/1999/xhtml'>...</h:p>