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

问题描述:

我无法理解exsl:node-set函数的工作原理。什么是exsl:node-set视为根节点?

我有一些XML,我正在扩大和使用动态填充exsl:节点集。假设它现在采用以下格式:

<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>元素的变量。这样做name($wrapNodeSet/*)获得这个匿名节点集的所有直接子节点的名称,在这种情况下,它只是单个的<nodes>元素的名称。

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

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

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

这将选择从与node-set()扩展获得的树中的任何nodes元件,即(所述nodes元件)具有tier属性具有值'b'

然后:

name($wrapNodeSet/*) 

产生第一节点包含在$wrapNodeSet第一子元素的名称。作为$wrapNodeSet包含恰好一个nodes元件和nodes元素只有node子元素,第一个这样的子元件是node元件和它的名称,因为任何node元素的名称是"node"

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

换句话说

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

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

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

你说“输出根节点的名称现在变成'node'” - 这很混乱,因为XPath 1.0中的“根节点”定义了从来没有名称的术语。你实际输出了什么?