1

我正在编写一个 XSL 模板,该模板从许多辅助来源中提取数据。示例辅助文档如下所示:

<toplevel xmlns:foo1="http://foo1">
 <path xmlns="http://foo1">
   <mytag>bar</mytag>
  </path>
</toplevel>

在 XSL 中,我这样做:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:foo1="http://foo1"
 exclude-result-prefixes="foo1">
  <xsl:variable name="secondary1" select="document('secondary1.xml')/toplevel"/>
  <foo>
    <xsl:value-of select="$secondary1//foo1:path/foo1:mytag"/>
  </foo>
</xsl:stylesheet>

由于有很多次要资源,每个资源都使用不同的命名空间,给每个标签添加前缀很乏味,而且这么多重复也不是正确的做法。有没有办法使用 document() 使得导入的节点集的命名空间被剥离(或以另一种方式实现相同的效果)?

4

2 回答 2

3

在 XPath/XSLT 1.0 中,要按名称选择名称空间限定的元素,您必须使用前缀。在 XSLT 2.0 中,您可以使用该xpath-default-namespace功能,它允许您为 XPath 表达式设置默认名称空间,因此您不必再使用前缀。有关更多详细信息,请参阅XSLT 2.0:xpath-default-namespace。您可以在样式表中的任何元素上使用此属性,并且除非被覆盖,否则它将对所有后代元素生效。(用 xsl 限定它:当您想将它放在非 XSLT 元素上时,即文字结果元素。)

在 XPath 1.0 中,您还可以通过本地名称选择元素,例如使用*[local-name() = 'path']/*[local-name() = 'mytag']. 在 XPath 2.0 中,为了更加简洁,您可以使用名称空间通配符,如 中所述*:path/*:mytag,如此处所述。这是一个有争议的补充,因为它似乎鼓励和/或证明您的系统显然正在使用同样可疑的命名空间。

于 2010-01-12T09:55:14.727 回答
2

从本质上讲,具有命名空间的节点与具有另一个命名空间的节点是完全不同的动物——即使它们碰巧共享相同的本地名称。(这与命名空间在其他任何地方的工作方式大致相同——实际上没有简单的方法可以“忽略”命名空间。在 C# 中引用类时考虑忽略命名空间。)

干净的方法是提及您可能在 XSLT 中遇到的每个名称空间并使用前缀,即使它看起来是重复的。

不太干净的方法是这样的:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:variable name="secondary1" select="document('secondary1.xml')"/>

  <xsl:template match="/">
    <foo source="1">
      <xsl:value-of select="
        $secondary1//*[local-name() = 'path']/*[local-name() = 'mytag']
      "/>
    </foo>
  </xsl:template>
</xsl:stylesheet>

这并不比使用前缀更令人赏心悦目,它更长更难阅读,它是模棱两可的,最后但并非最不重要的一点 - 它更慢,因为引擎必须在 XPath的每一步上测试一个谓词。任你选。

于 2010-01-12T09:44:10.673 回答