我正在编写一个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(),以便剥离导入的节点集的命名空间(或以另一种方式实现相同的效果)?
答案 0 :(得分: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
,as described here。这是一个有点争议的补充,因为它似乎鼓励和/或证明你的系统显然使用的命名空间的相同可疑使用。
答案 1 :(得分: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上每一步的谓词。随便挑选。