如何获取两个xpath节点集的交集

How to get the intersection of two xpath node sets

要获得两个不同节点集的并集,我可以使用 | 分隔符执行以下操作:

node.xpath(
    '(//C:Year[not(@value="2019")]) | (//R:Product[@value="Phone"])'
    , namespaces={'C': 'Columns', 'R': 'Rows'})

有没有办法在不知道这两条路径之间的关系(即允许它们以任何方式排序)的情况下获得两者之间的交集。我尝试了以下方法:

node.xpath('(//C:Year[not(@value="2019")]) and (//R:Product[@value="Phone"])', namespaces={'C': 'Columns', 'R': 'Rows'})

但是and似乎return一个bool而不是一个节点集。执行此操作的正确方法是什么?

我不确定分享 xml/xpath 表达式的好地方,但你可以去这里 https://extendsclass.com/xpath-tester.html 并在下面的 xpath 和 xml 中复制粘贴,它应该可以正常工作:

Expression: //C:Year[not(@value="2019")] | //R:Product[@value="Phone"]
XML:        <Data xmlns:R="Rows" xmlns:C="Columns" xmlns:V="Values"><R:ProductGroup value="Electronics"><R:Product value="Computer"><C:Year value="2018"><V:SumOfRevenue value="104"/><V:SumOfUnits   value="3"/></C:Year><C:Year value="2019"><V:SumOfRevenue value="82"/><V:SumOfUnits   value="9"/></C:Year><C:Year value="(all)"><V:SumOfRevenue value="186"/><V:SumOfUnits   value="12"/></C:Year></R:Product><R:Product value="Phone"><C:Year value="2018"><V:SumOfRevenue value="102"/><V:SumOfUnits   value="4"/></C:Year><C:Year value="2019"><V:SumOfRevenue value="99"/><V:SumOfUnits   value="12"/></C:Year><C:Year value="(all)"><V:SumOfRevenue value="201"/><V:SumOfUnits   value="16"/></C:Year></R:Product><R:Product value="(all)"><C:Year value="2018"><V:SumOfRevenue value="206"/><V:SumOfUnits   value="7"/></C:Year><C:Year value="2019"><V:SumOfRevenue value="181"/><V:SumOfUnits   value="21"/></C:Year><C:Year value="(all)"><V:SumOfRevenue value="387"/><V:SumOfUnits   value="28"/></C:Year></R:Product></R:ProductGroup><R:ProductGroup value="Media"><R:Product value="Movies"><C:Year value="2018"><V:SumOfRevenue value="25"/><V:SumOfUnits   value="12"/></C:Year><C:Year value="2019"><V:SumOfRevenue value="26"/><V:SumOfUnits   value="13"/></C:Year><C:Year value="(all)"><V:SumOfRevenue value="51"/><V:SumOfUnits   value="25"/></C:Year></R:Product><R:Product value="Theater"><C:Year value="2018"><V:SumOfRevenue value="17"/><V:SumOfUnits   value="3"/></C:Year><C:Year value="2019"><V:SumOfRevenue value="20"/><V:SumOfUnits   value="6"/></C:Year><C:Year value="(all)"><V:SumOfRevenue value="37"/><V:SumOfUnits   value="9"/></C:Year></R:Product><R:Product value="(all)"><C:Year value="2018"><V:SumOfRevenue value="42"/><V:SumOfUnits   value="15"/></C:Year><C:Year value="2019"><V:SumOfRevenue value="46"/><V:SumOfUnits   value="19"/></C:Year><C:Year value="(all)"><V:SumOfRevenue value="88"/><V:SumOfUnits   value="34"/></C:Year></R:Product></R:ProductGroup><R:ProductGroup value="(all)"><R:Product value="(all)"><C:Year value="2018"><V:SumOfRevenue value="248"/><V:SumOfUnits   value="22"/></C:Year><C:Year value="2019"><V:SumOfRevenue value="227"/><V:SumOfUnits   value="40"/></C:Year><C:Year value="(all)"><V:SumOfRevenue value="475"/><V:SumOfUnits   value="62"/></C:Year></R:Product></R:ProductGroup></Data>

一个可能的解决方案是使用 ancestor::RootName 为每个交叉路口 'go back to the root',因此我们将有:

//C:Year[not(@value="2019")]/ancestor::Data//R:Product[@value="Phone"]

还有其他方法吗?

在 XPath 2.0 中,使用 intersect 运算符。

在 XPath 1.0 中没有简单的方法

我想知道你是否真的想要这个路口。一组 C:Year 元素与一组 R:Product 元素的交集将是空的(没有元素可以是两个集合的成员——它可以是 C:YearR:Product 但不是两者。)。

所以我怀疑你想要的实际上不是集合交集,而是其他东西。但是我无法从你的问题中得出你想要的。