exsl:node-set将什么视为根节点?

时间:2012-07-02 10:04:28

标签: xslt exslt node-set

我无法理解exsl:node-set函数的工作原理。

我有一些XML,我正在扩展并使用它来动态填充exsl:node-set。我们说它目前采用以下格式:

<xsl:variable name="wrap">
    <nodes>
        <node/>
        <node/>
        <node/>
    </nodes>
</xsl:variable>
<xsl:variable name="wrapNodeSet" select="exsl:node-set($wrap)"/>

这可以根据需要工作并输出$ wrapNodeSet显示上面的节点标记。根节点名称使用名称显示为“节点”($ wrapNodeSet /*).

现在我需要扩展它以拥有2个节点并动态填充节点集。所以:

    <xsl:variable name="wrap">
    <nodes tier="a">
        <node/>
        <node/>
        <node/>
    </nodes>
    <nodes tier="b">
        <node/>
        <node/>
        <node/>
    </nodes>
</xsl:variable>
<xsl:variable name="wrapNodeSet" select="exsl:node-set($wrap)/nodes[@tier='b']"/>

输出节点集包括nodes元素,但输出根节点的名称现在更改为'node'。

有人可以解释为什么仍然输出nodes元素吗?

3 个答案:

答案 0 :(得分:0)

如果我正确地理解了你的问题,我相信“直观地”发生的事情(实际的幕后实现细节可能有点不同)在第一个例子中,你的变量指向'匿名节点集'包装<nodes>元素的变量。因此,name($wrapNodeSet/*)获取此匿名节点集的所有直接子节点的名称,在这种情况下,它只是单个<nodes>元素的名称。

在第二种情况下,您比匿名节点集更深入,变量直接包含单个nodes[@tier='b']元素。在这种情况下,name($wrapNodeSet/*)会选择该<nodes>元素的所有直接子元素,并将返回3个<node>个实例。如果你对此选择值为select,它将默认只显示第一个值,这就是你在输出中只看到“node”的原因。

要获取第二个实例的根名称,只需直接执行name($wrapNodeSet)即可看到“节点”。在第一个实例中执行$name(wrapNodeSet)将不会返回任何内容,因为匿名节点集没有名称。

答案 1 :(得分:0)

<xsl:variable name="wrapNodeSet" 
              select="exsl:node-set($wrap)/nodes[@tier='b']"/>

这将从使用nodes扩展程序获取的树中选择任何node-set()元素,(nodes元素)具有值为tier的{​​{1}}属性

然后:

'b'

生成name($wrapNodeSet/*) 中包含的第一个节点的第一个子元素的名称。由于$wrapNodeSet只包含一个$wrapNodeSet元素,而nodes元素只包含nodes个子元素,因此第一个这样的子元素是node元素及其name,因为任何node元素的名称为node

为什么你会在这个结果中看到任何意想不到的结果?

换句话说

"node"ext:node-set()上的应用在两种情况下产生相同的树,但在第二种情况下,您对$wrap的结果使用不同的,更长的XPath表达式 - 因此从评估这两个不同的XPath表达式得到的结果不同。

答案 2 :(得分:0)

exslt:node-set有一个非常非正式的规范,并且可能有关于哪些实现彼此不同的详细信息。在边缘情况下肯定是这样,例如,如果exstl:node-set的参数不是结果树片段,会发生什么。

我期望的行为是exslt:node-set()总是提供“根节点”(XPath 2.0称之为“文档节点”)。 XPath 1.0中定义的根节点没有名称。在第一个示例中,根节点有一个名为“nodes”的元素子节点。在第二个示例中,根节点有两个元素子节点,两个元素都具有名称“nodes”。

您说“输出根节点的名称现在更改为'node'” - 这令人困惑,因为XPath 1.0中的“根节点”定义了术语永远不会有名称。你实际输出了什么?