使用 XPath 选择没有指定中间节点的后代节点

Using XPath to select a descendant node that doesn't have a specified intermediate node

提问人:fractor 提问时间:10/31/2023 最后编辑:fractor 更新时间:11/1/2023 访问量:45

问:

使用 XPath 2.0(理想情况下)或 3.0(一个选项),我想选择一个节点,只要从 到 的路径不包含任何节点,它就是 XPath 的后代。CAACB

<Root>
  <Other>
    <A>
      <Other>
        <C/> <!--selected-->
      </Other>
      <Other>
        <B>
          <Other>
            <C/> <!--not selected-->
          </Other>
        </B>
      </Other>
    </A>
  </Other>
</Root>

Other表示 0 个或多个嵌套的非节点。B

A可能有祖先。B

XPath XPath-2.0

评论

2赞 Martin Honnen 10/31/2023
好吧,对于所示的例子就足够了,但当然,如果可以有元素的祖先,那就不够了。//A//C[not(ancestor::B)]BA
0赞 choroba 10/31/2023
哪个版本的 XPath?
0赞 fractor 10/31/2023
是的,@MartinHonnen,可以有 .BA
0赞 fractor 10/31/2023
@choroba XPath 2.0。learn.microsoft.com/en-us/dotnet/api/......
0赞 fractor 11/1/2023
显然不是 XPath 2.0(参见 stackoverflow.com/a/77397462/3051702)。

答:

2赞 Martin Honnen 11/1/2023 #1

使用 XPath 2.0,我认为就足够了。但请注意,Microsoft 的 XPath 实现是 XPath 1.0。//A//C[not(ancestor::B intersect ancestor::A[1]//B)]

评论

0赞 fractor 11/1/2023
看起来不错,谢谢。现在我只需要理解它。:)感谢您对 XPath 版本的指导。当Microsoft说他们使用XPath 2.0数据模型时,这并不意味着XPath 2.0。
2赞 Martin Honnen 11/1/2023
@fractor,我认为当他们设计该 API 并记录它时,他们也在努力实现 XPath 2.0 和 XSLT 2.0,但最终取消了该计划,转而将 LINQ to XML 作为 Microsoft 的 XPath 2 和 XQuery 1 的 W3C 标准的替代方案Microsoft。 但 .NET Framework 和 .NET Core (又名 .NET 6 或更高版本)中的 Microsoft XPath 堆栈仅实现 XPath 1.0。
2赞 Michael Kay 11/1/2023 #2

我会写

//A/(.//C except .//B//C)

除非它是一个非常大的文档并且性能是一个问题,在这种情况下,我可能会实现我自己的传递闭包。(child::* except child::B)