抓取不是其他节点后代的节点,不包括当前上下文

Posted

技术标签:

【中文标题】抓取不是其他节点后代的节点,不包括当前上下文【英文标题】:Grabbing nodes that aren't descendants of other nodes, excluding the current context 【发布时间】:2011-08-02 15:47:41 【问题描述】:

所以,我不知道如何真正表达这个问题。我想要一个节点列表,并且只选择一个节点,而不是嵌套节点。例如:

<root>
    <my_element>
        <my_element>
            Some Text
        </my_element>
    </my_element>
</root>

我知道我已经可以使用这个 xpath 做一些我想做的事情了:

Context: /
xPath: descendant::my_element[not(ancestor::my_element)]

哪个会返回这个结果集:

<root>
    [<my_element>]
        <my_element>
            Some Text
        </my_element>
    [</my_element>]
</root>

这是我想要的预期行为。但我希望能够将上下文更改为:

/my_element

并得到这个结果集:

<root>
    <my_element>
        [<my_element>]
            Some Text
        [</my_element>]
    </my_element>
</root>

我已经尽我所能查看 xPath 文档,但我没有想出任何东西。也许这里有人可以提供一些见解?

谢谢!

编辑 - 我希望能够选择一个 my_element 后代,它不是 my_element 的祖先,不包括上下文节点。

再次编辑 - 进一步解释。

我想要一个 xpath 查询来选择 my_element 的节点,只要该节点不是 my_element 的子节点。但是,如果 xpath 上下文设置为 my_element 节点,那么我不希望该节点计入表达式。因此 xpath 将匹配下一个 my_element 节点,即使它实际上是 my_element 的子节点。

再次编辑 -

这里还有一些例子。

<root>
    <a>
        <a>
            <b>
                <a>
                    Hello!
                </a>
            </b>
            <a>
                <b>
                    Hello Again
                    <a>
                        Sub
                    </a>
                </b>
            </a>
        </a>
    </a>
</root>

Context: /root/
Desire: Want to grab all A nodes, so long as they aren't a descendant of A

Result:
<root> == Context
    [<a>]
        <a>
            <b>
                <a>
                    Hello!
                </a>
            </b>
            <a>
                <b>
                    Hello Again
                    <a>
                        Sub
                    </a>
                </b>
            </a>
        </a>
    [</a>]
</root>

Context: /root/a/
Desire: Want to grab all A nodes, so long as they aren't a descendant of A, not including the context /root/a/

Result:
<root>
    <a> == Context
        [<a>]
            <b>
                <a>
                    Hello!
                </a>
            </b>
            <a>
                <b>
                    Hello Again
                    <a>
                        Sub
                    </a>
                </b>
            </a>
        [</a>]
    </a>
</root>

Context: /root/a/a/
Desire: Want to grab all A nodes, so long as they aren't a descendant of A, not including the context /root/a/a/

Result:
<root>
    <a>
        <a> == Context
            <b>
                [<a>]
                    Hello!
                [</a>]
            </b>
            [<a>]
                <b>
                    Hello Again
                    <a>
                        Sub
                    </a>
                </b>
            [</a>]
        </a>
    </a>
</root>

Context: /root/a/a/a/
Desire: Want to grab all A nodes, so long as they aren't a descendant of A, not including the context /root/a/a/a/

Result:
<root>
    <a>
        <a>
            <b>
                <a>
                    Hello!
                </a>
            </b>
            <a> == Context
                <b>
                    Hello Again
                    [<a>]
                        Sub
                    [</a>]
                </b>
            </a>
        </a>
    </a>
</root>

我希望这能让我的愿望更加清晰。感谢所有努力的人!

【问题讨论】:

@Kyle:这些不只是my_element 孩子吗?除非你想要一个 my_element 后代,它没有 my_element 祖先,不包括上下文节点及其祖先。 你的后者是正确的。我希望能够选择一个 my_element 后代,它不是 my_element 的祖先,不包括上下文节点。 @Kyle:我认为你不能在 XPath 1.0 中因为需要引用上下文节点。 @Alejandro:如果我将上下文放在 xpath 中并在那里进行检查,是否有可能?即:/my_element/descendant::my_element[not(ancestor::my_element)] @Kyle:不。我能想到的唯一表达式是./descendant::my_element[1],它选择第一个后代(那时它不会有my_element祖先)但它不会选择其余的my_element 在其他上下文节点子分支中。 【参考方案1】:

使用

//my_element[not(.//my_element)]

这会选择所有名为 my_element 且没有任何 my_element 后代的元素。

【讨论】:

这不会选择最外层的my_elementroot 作为上下文节点。 @Alejandro:对不起,你能解释一下吗? OP 想要:“我希望能够选择一个 my_element 后代,它不是 my_element 的祖先,不包括上下文节点”——这就是我的答案中的 XPath 表达式所选择的。 ??? 不完全。看,这会起作用,除非我想从测试中排除上下文节点,这可以通过 my_element.实际上,再次阅读您的内容,您完全错了我想要的。没问题。看到这个 xpath:descendant::my_element[not(ancestor::my_element)]。这很好用。除了将 xpath 上下文设置为 my_element 时,在这种情况下,我不希望 xpath 表达式关心父级(上下文节点)。所以这样的事情会起作用,如果它是实际有效的 xpath: descendant::my_element[not(ancestor::my_element) except context] @Kyle:我愿意提供帮助。这里的主要问题是您直到现在还没有以人们可以理解的方式解释问题(我绝对不 - “排除”是什么意思?)。请编辑您的问题并解释清楚。 @Alejandro,如果您理解这个问题,请编辑它,以便包括我在内的更多人能够理解它。凯博士似乎也遇到了同样的困难。 @Kyle:提示。提供一个简单的例子。不要使用诸如my_element 之类的名称——它们会造成混淆。使用ABC。在示例中定义哪个是初始上下文节点。然后枚举必须选择的节点。最后,说明选择应满足哪些要求。【参考方案2】:

我认为您可能落入了一个常见的陷阱。您的数据上的 XPath 表达式 /root/my_element 将仅选择一个元素 - 最外层的 my_element 节点。但是那个节点仍然连接到它的父节点、兄弟节点和子节点。当您显示选择的结果时,该节点通常会与其子节点(实际上是所有后代)一起显示 - 不是因为 XPath 选择了子节点,而是因为这是显示被选择的单个节点的一种友好方式。

另一方面,我再次阅读了这个问题,但我可能错了 - 我从您用来显示 XPath 表达式结果的特殊符号中猜到了。

表达式 /my_element 只有当它的父节点是树根节点的文档节点时才会选择 my_element,无论您的上下文节点是什么,您的输入都不会出现这种情况。当然,您可以将以 my_element 为根的子树复制到新文档中,在这种情况下,此表达式将起作用。

【讨论】:

OP 要求提供与此 XPath 2.0 表达式 .//my_element except .//my_element//my_element 等效的 XPath 1.0 表达式

以上是关于抓取不是其他节点后代的节点,不包括当前上下文的主要内容,如果未能解决你的问题,请参考以下文章

XSLT/XPath 中的当前节点与上下文节点?

使用MySQL 8.0递归CTE查找层次结构表中的直接后代并传播给父级

怎样遍历当前节点的所有后代节点

XPath / XQuery:在节点中查找文本,但忽略特定后代元素的内容

如何在节点redis中设置hmset的过期时间?

Java 上下文 sax / stax 解析