5

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

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

Edit2:对于 dimitre 和所有有类似问题的人

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

只是 XSLT(向上)返回给我一个奇怪的结果,@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

4 回答 4

5

恭喜亚当得到了一个非常快速的第一个答案。

只是添加一点细节:

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

ancestor::node()

... 将按以下顺序返回一个序列:

  1. item[@title='b']
  2. item[@title='a']
  3. 元素(root又名文档元素)
  4. 根节点_ /

要获得您列出的具体结果,您需要:

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 指令另有说明)。

于 2012-09-11T12:42:07.830 回答
3

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

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

要选择所有祖先,请使用

ancestor::node()

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

要选择所有元素祖先,请使用

ancestor::*

这类似于前面的表达式,但不选择根节点( /),因为它不是元素。

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

ancestor::item

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

注意2:我强烈建议在学习 XPath 时使用XPath Visualizer 之类的工具。多年来,这个工具已经帮助成千上万的人以有趣的方式学习 XPath —— 通过使用 XPath 表达式并观察他们的评估结果。

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

于 2012-09-11T12:42:56.503 回答
2

您可以使用 xpathancestor::item

于 2012-09-11T12:34:33.533 回答
1

您输出bcdx而不是输出的原因ab是因为您<xsl:for-each>正在迭代所选元素的所有itemitem元素,而不仅仅是迭代$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>
于 2012-09-11T23:11:46.490 回答