【问题标题】:XPath - get parent of text nodes with conditionXPath - 获取有条件的文本节点的父节点
【发布时间】:2015-05-21 10:31:15
【问题描述】:
<doc ok="yes">
    <a>
        <b>
            <c>
                aa
                <d ok="yes">
                    bb
                </d>
                cc
            </c>
        </b>
    </a>
    <e>
        ee
    </e>
    <f ok="no">
        no
    </f>
</doc>

我需要使用 XPath 检索节点列表,其中每个节点必须满足以下条件:

  1. 节点至少有一个子文本节点

  2. 如果节点(或祖先轴上最近的节点)具有属性"ok",则值必须为"yes"

  3. 当任何祖先是结果的一部分时,排除节点

所以在我的示例中,我想得到&lt;c&gt;&lt;e&gt;。节点&lt;d&gt; 被排除在外,因为它是&lt;c&gt; 的子节点,它是结果的一部分。

我从条件 (1) 开始使用这个表达式 //*[count(./text()[normalize-space()])&gt;0]。它返回&lt;c&gt;&lt;d&gt;&lt;e&gt;&lt;f&gt;。我不知道如何排除&lt;d&gt;

【问题讨论】:

    标签: xpath


    【解决方案1】:

    我会将其分为两个步骤。 首先,只考虑条件号 1 和 2。

    //*[text()[normalize-space()]]
       [
          ancestor-or-self::*[not(@ok)] 
            or 
          ancestor-or-self::*[@ok][1][@ok='yes']
        ]
    

    给定有问题的 XML 作为输入,上面的 xpath 返回 3 个元素:&lt;c&gt;&lt;d&gt;&lt;e&gt;

    下一步将实现条件编号 3。这可以通过重复在第一步中使用的相同谓词来完成,但现在是 ancestor::* 而不是当前节点。然后使用not() 否定重复谓词,因为我们希望祖先不满足条件 1 和 2(我们希望当前节点的祖先不是结果的一部分):

    [not(
            ancestor::*[text()[normalize-space()]]
            [
                ancestor-or-self::*[not(@ok)] 
                    or 
                ancestor-or-self::*[@ok][1][@ok='yes']
            ]
        )
    ]
    

    将这两个步骤组合在一起,您将获得以下 xpath:

    //*[text()[normalize-space()]]
       [
          ancestor-or-self::*[not(@ok)] 
            or 
          ancestor-or-self::*[@ok][1][@ok='yes']
        ]
        [not(
                ancestor::*[text()[normalize-space()]]
                [
                    ancestor-or-self::*[not(@ok)] 
                        or 
                    ancestor-or-self::*[@ok][1][@ok='yes']
                ]
            )
        ]
    

    最终 xpath 中的每个外部谓词 ([]) 按顺序表示条件 1、2 和 3。

    【讨论】:

    • 这里可能有一个小错字:祖先*[text()[normalize-space()]],但除此之外它就像一个魅力,谢谢
    猜你喜欢
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多