如何在 XSLT 中动态生成命名空间 XML 属性?

How to generate namespaced XML attribute dynamically in XSLT?

如何在 XSLT 中动态生成命名空间 XML 属性?例如,我们可以有以下 XML 文档使用不同的属性,例如 attr1:fooattr2:bar:

<a xmlns="http://example.com/"
   xmlns:attr1="http://example.com/attr1#"
   xmlns:attr2="http://example.com/attr2#">
  <b attr1:foo=""/>
  <b attr2:bar=""/>
</a>

假设我们要转换文档并将所有属性的值更改为...。我们应该如何构造这些属性?如何解决这个问题的一个自然选择是使用 <xsl:attribute>. But what QName should we use as its name attribute? The function name() 可以 return 属性的 QName 作为字符串。朴素的 XSL 模板可能如下所示:

<xsl:template match="@*">
  <xsl:attribute name="{name()}">...</xsl:attribute>
</xsl:template>

但是,由于 name() return 将 QName 作为字符串,此解决方案需要通过 XSLT 中的 xmlns 预定义命名空间前缀绑定(例如,xmlns:attr1="http://example.com/attr1#").

然后我想知道是否可以使用 <xsl:attribute>namespace 属性:

<xsl:template match="@*">
  <xsl:attribute name="{local-name()}"
                 namespace="{namespace-uri()}">...</xsl:attribute>
</xsl:template>

这个解决方案似乎可行,但我认为这不是 XSLT 中的最佳实践。你知道更好的解决方案吗?

这取决于您对源文档的结构了解多少:

  • 如果您知道所使用的命名空间及其前缀绑定,那么 在您的样式表中声明它们并使用您所谓的“朴素 XSL 模板”。

  • 否则复制名称空间 (URI),如第二个模板中所示。


另请注意,您可以按如下方式组合两者:

<xsl:template match="@*">
    <xsl:attribute name="{name()}" namespace="{namespace-uri()}">...</xsl:attribute>
</xsl:template>

对于某些处理器(例如 Saxon 6.5),这将确保在结果中重新使用原始前缀;其他处理器(例如 libxslt 和 Xalan)无论如何都会这样做。