node-set()是否有祖先节点?

时间:2015-03-30 21:42:34

标签: xslt

我觉得,这是一个基本的XSLT问题。根据我的理解,节点集本身就是数据结构。从node-set()我无法导航到集合之外的任何节点。即我无法到达父母,xml的开头及其兄弟姐妹。这是对的吗?

有没有办法获得node-set()

的父级

代码

<neighbourhood>
<parent name = "xyz">
<child address=10> a </child>
<child address=10> b </child>
<child address=15> c </child>
</parent>
</neighbourhood>

我有一组子节点。我需要消除具有重复“地址”的节点。 可以有n个'parent'和m个'child',并且'child'可以有祖父节点。

最好的和合乎逻辑的方式可能是由每个父母去处理他们的孩子。但是,它是一个现有的代码库,这是一个过于简单的例子。我不想通过触摸调用函数和其他模板来破解太多东西。

所以,我的问题是我是否可以通过我所拥有的'子'节点集来获取'父级'

感谢您的所有回复

3 个答案:

答案 0 :(得分:3)

  

node-set()是否有祖先节点?

node-set()是(扩展)函数 - 不是节点。函数不能具有祖先,因为它不是节点。

我认为问题中"node-set()"表示xxx:node-set()函数返回的值(前缀&#34; xxx&#34;绑定到特定于供应商的值)命名空间)。如果是这样,这是通缉答案:

根据定义,xxx:node-set()函数会返回临时树的 document-node() (在XPath 1.0中也称为root-node),这是通过转换获得的RTF(结果树片段),作为此函数的唯一参数传递。

按定义,文档节点位于文档层次结构的顶部,是XML文档中唯一没有父文档的节点。

因此,被调用的xxx:node-set()函数返回的节点没有任何祖先

  

从node-set()我无法导航到集合之外的任何节点。即我无法到达父母,xml的开头及其兄弟姐妹。这是对的吗?

是的,不调用另一个从另一个文档返回节点的函数(例如标准XPath函数id()或标准XSLT函数document()),或者引用变量/参数,它不是只能通过使用XPath位置步骤从其他文档导航到节点。

  

     

有没有办法获得node-set()

的父级

不,xxx:node-set()函数返回的节点是文档节点,文档节点没有父节点(或任何其他祖先节点)。

答案 1 :(得分:2)

不要混淆节点集和node-set() s。

这是什么意思?嗯,节点集是一组节点。在正常的,未扩展的XSLT 1.0中,这意味着从输入文档中选择节点。如果我这样做:

<!-- a node set -->
<xsl:variable name="my-node-set"
    select="/indoc/level1/level2"/>

变量$my-node-set包含一组level2个节点,但这些节点仍然存在于输入文档中。如果我随后这样做for-each

<nodeset-from-indoc>
    <xsl:for-each select="$my-node-set/level3">
         <parent>
             <xsl:value-of select="local-name(..)"/>
         </parent>
         <grandparent>
             <xsl:value-of select="local-name(../..)"/>
         </grandparent>
     </xsl:for-each>
 </nodeset-from-indoc>

获取每个节点的父母和祖父母的姓名:

<nodeset-from-indoc>
    <parent>level2</parent><grandparent>level1</grandparent>
    <parent>level2</parent><grandparent>level1</grandparent>
    <parent>level2</parent><grandparent>level1</grandparent>
</nodeset-from-indoc>

但是,如果我将节点硬编码为变量:

<!-- a result-tree fragment -->
<xsl:variable name="my-rtf">
    <level2>
        <level3>1</level3>
    </level2>
    <level2>
        <level3>2</level3>
    </level2>
    <level2>
        <level3>3</level3>
    </level2>
</xsl:variable>

这是一个节点集,而是一个结果树片段,因为它们没有从输入文档中选择。结果树片段的问题在于您无法在其上使用XPath。例如,我不能这样做:

<xsl:for-each select="$my-rtf/level3">

这是node-set()函数的用武之地。它是XSLT 1.0的扩展,它来自某些扩展名称空间,具体取决于您的XSLT处理器。许多处理器选择在EXSLT定义的命名空间中实现它。

正如Dmitre指出的那样,node-set()函数返回临时树的魔术文档节点,允许您使用XPath。 然而,这会导致选择需要完成的微妙转变。由于魔术文档节点,我必须在我的选择中包含level2

<nodeset-from-rtf>
    <xsl:for-each select="exsl:node-set($my-rtf)/level2/level3">
        <parent>
            <xsl:value-of select="local-name(..)"/>
        </parent>
        <grandparent>
            <xsl:value-of select="local-name(../..)"/>
        </grandparent>
    </xsl:for-each>
</nodeset-from-rtf>

在这种情况下,level3节点将有父母,但没有祖父母:

<nodeset-from-rtf>
    <parent>level2</parent><grandparent/>
    <parent>level2</parent><grandparent/>
    <parent>level2</parent><grandparent/>
</nodeset-from-rtf>

答案 2 :(得分:2)

节点集是一组节点。节点集中的每个节点都有祖先。节点集本身没有。如果$ NS是一个节点集,你可以$NS/ancestor::node():这将为你提供节点集中所有节点的所有祖先,并删除重复项。