3

我无法理解 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']"/>

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

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

4

3 回答 3

0

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

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

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

于 2012-07-02T11:05:33.880 回答
0

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

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

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

于 2012-07-02T12:15:27.927 回答
0
<xsl:variable name="wrapNodeSet" 
              select="exsl:node-set($wrap)/nodes[@tier='b']"/>

这将从通过扩展nodes获得的树中选择任何元素,该元素(元素)具有value 属性。node-set()nodestier'b'

然后:

name($wrapNodeSet/*)

生成包含在 中的第一个节点的第一个子元素的名称$wrapNodeSet。As只$wrapNodeSet包含一个nodes元素,并且该nodes元素只有node子元素,第一个这样的子元素是一个node元素及其名称,因为任何node元素的名称都是"node".

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

换句话说

在这两种情况下应用ext:node-set()on$wrap会生成相同的树,但在第二种情况下,您对结果使用不同的、更长的 XPath 表达式,ext:node-set($wrap)因此您从这两个不同的 XPath 表达式的求值中得到不同的结果。

于 2012-07-02T12:09:44.980 回答