XSL节点集:按名称找不到子元素

时间:2018-08-10 13:46:33

标签: xml xslt

我是xsl的初学者,所以也许这是一个非常简单的问题。 我有一个xsl文件,我想在其中找到在param-object中定义的特定值:

<xsl:param name="locales">
    <label name="testname"><locale name="de">german text</locale><locale name="en">english text</locale></label>
</xsl:param>

<xsl:template match="foo">
    <topLevelElement xmlns="http://foo.bar.org">
        <xsl:value-of select="ext:node-set($locales)/label[@name='testname']/locale[@name='en']"/>
    </topLevelElement>
</xsl:template>

我希望获得值“英语文本”,因为我想在参数locales中找到名称为label的{​​{1}}。我想在那里找到一个名为testname的{​​{1}}。但这是行不通的。  当我用星号替换特定元素(标签和语言环境)的名称时,它会起作用:

    

locale

有人可以告诉我为什么我找不到孩子的名字吗? 非常感谢!

修改: 该代码未显示名称空间(我想它是由浏览器解释的)。在开头和结尾处都没有括号:

  

xsl:stylesheet xmlns:xsl =“ http://www.w3.org/1999/XSL/Transform” xmlns =“ http://foo.bar.org” xmlns:ext =“ http://exslt.org/common” version =“ 1.0” xsl:output method =“ xml” version =“ 1.0” encoding =“ UTF-8” /

2 个答案:

答案 0 :(得分:4)

所以你有

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://foo.bar.org"
    xmlns:ext="http://exslt.org/common"
>

,这定义了默认的名称空间。这意味着XSLT程序创建的每个XML元素(未使用命名空间明确创建)将在该命名空间中。这也适用于您不输出的任何元素。

这意味着您不能再使用“普通” XPath选择这些元素,因为普通XPath假定元素不在任何命名空间中。

ext:node-set($locales)/label[@name='testname']/locale[@name='en']

查找没有名称空间的<label>元素和没有名称空间的<locale>元素。在XPath中引用名称空间的方法是使用前缀。

因此,您可以为此名称空间添加前缀,仅用于内部处理。

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://foo.bar.org"
    xmlns:foo="http://foo.bar.org"
    xmlns:ext="http://exslt.org/common"
>

此处"http://foo.bar.org"命名空间声明为 default ,但也具有前缀foo。现在您可以执行以下操作:

ext:node-set($locales)/foo:label[@name='testname']/foo:locale[@name='en']

一切都会开始起作用。


就我个人而言,我不会使用<xsl:param>。我将建立一个没有名称空间的补充XML文档,将其命名为locales.xml,然后执行以下操作:

<!-- top-level -->
<xsl:variable name="locales" select="document('locales.xml')" />

<!-- ...later -->
<xsl:value-of select="$locales/*/label[@name='testname']/locale[@name='en']" />

这样,既不需要帮助程序名称空间,也不需要ext:node-set(),并且模块化程度更高。

答案 1 :(得分:3)

在不更改XPath的情况下进行修复的一种方法是更改​​

<xsl:param name="locales">
    <label name="testname"><locale name="de">german text</locale><locale name="en">english text</locale></label>
</xsl:param>

<xsl:param name="locales" xmlns="">
    <label name="testname"><locale name="de">german text</locale><locale name="en">english text</locale></label>
</xsl:param>