xml 获取当前节点的所有祖先

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12369734/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 13:40:51  来源:igfitidea点击:

Get all ancestors of current node

xmlxsltxpathxslt-1.0

提问by Moriarty

I want to get all ancestors of current node:

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

XML:

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>

Result:

结果:

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

Edit: Answers with axes ancestor are fine. My problem was elsewhere, in XSLT

编辑:轴祖先的答案很好。我的问题在别处,在 XSLT 中

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>

Returns:

返回:

bcdx


Edit2:for dimitre and for all who have a similar problem

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

All the answers to my question were good.

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

Just XSLT (up) returns to me a strange result and @Mads Hansen corrected me.

只是 XSLT(向上)返回给我一个奇怪的结果,@Mads Hansen 纠正了我。

FINAL WORKING EXAMPLE:

最终工作示例:

XML:

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:

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>

Returns:

返回:

ab

采纳答案by Sean B. Durkin

Congradulations to Adam for a very quick first answer.

祝贺亚当很快得到了第一个答案。

Just to add a little detail:

只是补充一点细节:

Your listed expected result does not match your words. the root element also an ancestor node and the document is also an ancestor node.

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

ancestor::node()

... will return a sequence in this order:

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

  1. item[@title='b']
  2. item[@title='a']
  3. the rootelement (a.k.a. the document element)
  4. the root node/
  1. item[@title='b']
  2. item[@title='a']
  3. 所述root元件(又名文档元素)
  4. 所述根节点/

To get the specific result you listed, you need:

要获得您列出的特定结果,您需要:

ancestor::item/.

The effect of the /. is to change the ordering back to forward document order. The native order of ancestor:: is reverse document order.

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



Update: Illustration of points made in the comment feed.

更新:评论提要中提出的观点的插图。

This style-sheet (with OP's input)...

这个样式表(带有 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>

... will output 'ba' illustrating the point that ancestor:: is indeed a reverse axis. And yet this style-sheet ...

... 将输出 '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>

... has the opposite result 'ab' . This is instructive because it shows that in XSLT 1.0 (not so in XSLT 2.0), the brackets remove the reverse nature, and it becomes a document ordered node-set.

... 有相反的结果 'ab' 。这是有指导意义的,因为它表明在 XSLT 1.0 中(在 XSLT 2.0 中不是这样),括号去除了相反的性质,并且它变成了一个文档有序节点集。

The OP has asked about a transform something like....

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>

This one returns 'ab' (in XSLT 2.0 it would return 'ba'). Why? Because in XSLT 1.0, the xsl:for-each instruction ignores the reverse-ness of the axis and processes in document order (unless an xsl:sort instruction says otherwise).

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

回答by Dimitre Novatchev

I want to get all ancestors of current node

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

The designated nodes obviously aren't allancestors of the "green" node.

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

To select allancestors use:

要选择所有祖先,请使用

ancestor::node()

This selects all ancestor nodes of the initial conext node (or current node), including the top element and its parent -- the root node/-- which is a node, but isn't an element.

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

To select all elementancestors use:

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

ancestor::*

This is similar to the previous expression, but doesn't select the root node(/), because it isn't an element.

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

To select all ancestors named item, use:

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

ancestor::item

Do Note: All expressions above assume that (//item[@title='c'])[1]is the initial context node (current node). If this assumption is not correct, then (//item[@title='c'])[1]/must be prepended to each of the expressions.

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

Note2: I strongly recommend for learning XPath to use a tool like the XPath Visualizer. For many years this tool has helped many thousands of people learn XPath the fun way -- by playing with XPath expressions and observing the result of their evaluation.

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

Note: The XPath Visualizer was created by me in year 2000 and was never a financial product. I am recommending it based solely on its value to the users, proven in the course of many years

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

回答by Adam Hopkinson

You can use the xpath ancestor::item

您可以使用 xpath ancestor::item

回答by Mads Hansen

The reason why you were outputting bcdxinstead of abis because your <xsl:for-each>is iterating over all of the itemchildren of the selected itemelements, rather than just iterating over the selected elements in the $testvariable.

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

Change your for-each to just iterate over $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>