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

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

在 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 解析器持悲观态度似乎是明智的) .尝试使用 <output method='html'/> XSLT 元素不会对输出产生影响。 XHTML Compatibility Guidelines 没有提到名称空间,这让人感到意外。添加文档类型声明,甚至 <meta http-equiv=''...> hack 以提示 application/xhtml+xml,似乎对浏览器的行为没有任何影响。

我在 XSLT 1.0 规范中看不到任何控制它的内容。那里提到的名称空间别名正在解决一个不同的问题;使用 XSLT 中的默认命名空间并没有提供 libxslt 似乎倾向于采用的任何提示。其他 stackexchange 问题(例如 or this one)似乎主要是对 XSLT 和名称空间的误解。我确信在我漫长的 XSLT 过去的某个时候我已经设法实现了这一点,但如果我做到了,我就无法复活它。

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

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

如果我找错了树,或者如果 EPUB 处理器被认为对命名空间更敏感,以至于我实际上是在解决问题的错误部分,我愿意接受这些信息还有。

你需要转型

<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 世界中,您也可以期待一些一致性。