获取当前节点的所有祖先

时间:2012-09-11 12:28:51

标签: xml xslt xpath xslt-1.0

我想获得当前节点的所有祖先:

XML:

<root>
   <item title="a">
       <item title="b">               
           <item title="c"></item> <!--CURRENT-->
           <item title="d"></item>                 
        </item> 
       <item title="x">             
           <item title="y"></item> 
           <item title="z"></item>  
       </item>            
   </item> 
</root>

结果:

<item title="a">...</item>
<item title="b">...</item>

编辑: 轴祖先的答案很好。 我的问题出在其他地方,在XSLT中

XSLT:

<xsl:variable name="curr" select="//item[@title = 'c']"></xsl:variable>
<xsl:variable name="test" select="$curr/ancestor::item"></xsl:variable>

<xsl:for-each select="$test/item">
<xsl:value-of select="@title"></xsl:value-of>
</xsl:for-each>

返回:

bcdx

dimitre以及所有有类似问题的人

Edit2:

我的问题的所有答案都很好。

只是XSLT(up)给我一个奇怪的结果,而@Mads Hansen纠正了我。

最终工作示例:

XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
   <item title="a">
       <item title="b">               
           <item title="c"></item> 
           <item title="d"></item>                 
        </item> 
       <item title="x">             
           <item title="y"></item> 
           <item title="z"></item>  
       </item>            
   </item> 
</root>

XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:variable name="curr" select="//item[@title = 'c']"></xsl:variable>
        <xsl:variable name="test" select="$curr/ancestor::item"></xsl:variable>

        <xsl:for-each select="$test">
            <xsl:value-of select="@title"></xsl:value-of>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

返回:

ab

4 个答案:

答案 0 :(得分:5)

向Adam致以最快速的第一个答案。

只是添加一些细节:

您列出的预期结果与您的字词不符。根元素也是祖先节点,文档也是祖先节点。

ancestor::node()

...将按此顺序返回一个序列:

  1. item[@title='b']
  2. item[@title='a']
  3. root元素(a.k.a。文档元素)
  4. root node /
  5. 要获得列出的具体结果,您需要:

    ancestor::item/.
    

    /的效果。是将订购更改回转发文件订单。祖先::的本机顺序是反向文档顺序。


    更新:评论供稿中点数的插图。

    此样式表(带OP输入)......

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    
    <xsl:template match="/">
      <xsl:for-each select="//item[@title='c']">
        <xsl:value-of select="ancestor::item[1]/@title" />
        <xsl:value-of select="ancestor::item[2]/@title" />
      </xsl:for-each>  
    </xsl:template>         
    </xsl:stylesheet>
    

    ...将输出'ba',说明祖先::确实是反向轴的点。然而这个样式表......

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    
    <xsl:template match="/">
      <xsl:for-each select="//item[@title='c']">
        <xsl:value-of select="(ancestor::item/@title)[1]" />
        <xsl:value-of select="(ancestor::item/@title)[2]" />
      </xsl:for-each>  
    </xsl:template>
    
    </xsl:stylesheet>
    

    ......结果相反'ab'。这是有启发性的,因为它表明在XSLT 1.0中(在XSLT 2.0中不是这样),括号删除了反向性质,它变成了文档有序节点集。

    OP已经询问了类似......的变换。

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    
    <xsl:template match="/">
      <xsl:for-each select="//item[@title='c']">
        <xsl:for-each select="ancestor::item">
          <xsl:value-of select="@title" />
        </xsl:for-each>
      </xsl:for-each>  
    </xsl:template>
    
    </xsl:stylesheet>
    

    这个返回'ab'(在XSLT 2.0中它将返回'ba')。为什么?因为在XSLT 1.0中,xsl:for-each指令忽略了轴的反向性并按文档顺序处理(除非xsl:sort指令另有说明)。

答案 1 :(得分:3)

  

我想获得当前节点的所有祖先

指定的节点显然不是“绿色”节点的所有祖先。

选择所有祖先使用

ancestor::node()

这将选择初始conext节点(或当前节点)的所有祖先节点,包括顶部元素及其父元素 - root node / - 这是一个节点,但不是一个元素。

选择所有元素祖先使用

ancestor::*

这与前一个表达式类似,但不选择root node/),因为它不是元素。

要选择名为item的所有祖先,请使用

ancestor::item

请注意:以上所有表达式都假设(//item[@title='c'])[1]是初始上下文节点(当前节点)。如果此假设不正确,则必须在每个表达式前加(//item[@title='c'])[1]/

Note2 :我强烈建议学习XPath以使用 the XPath Visualizer 等工具。多年来,这个工具帮助成千上万的人学习XPath的有趣方式 - 通过使用XPath表达式并观察他们的评估结果。

注意:XPath Visualizer是我在2000年创建的,从来不是一个金融产品。我建议它完全基于它对用户的价值,经过多年的证明

答案 2 :(得分:2)

您可以使用xpath ancestor::item

答案 3 :(得分:1)

您输出bcdx而不是ab的原因是因为您的<xsl:for-each>正在迭代所选item元素的所有item个子元素,而不是仅仅迭代$test变量中的选定元素。

将您的for-each更改为仅对$test进行迭代:

<xsl:variable name="curr" select="//item[@title = 'c']"></xsl:variable>
<xsl:variable name="test" select="$curr/ancestor::item"></xsl:variable>

<xsl:for-each select="$test">
    <xsl:value-of select="@title"></xsl:value-of>
</xsl:for-each>