如何在 xpath 中选择备用子路径



这有效:

(//someparentpath/h3 | //someparentpath/ul/li/div)/somechildpath

这不:(为什么?

//someparentpath/(h3 | ul/li/div)/somechildpath

XPath 1.0 的语法不允许轴步长交替,请参阅节点集的规范或尝试 XPath 1.0 语法测试页面。语法允许第一个查询,第二个查询无效的 XPath 1.0。

如果有机会,请切换到 XPath 2.0 实现,它为查询 XML 提供了更多的可能性。这两个查询都是有效的 XPath 2.0 语句。

XPath 1.0 中,您必须:

  • 完全写出路径两次并使用它们的并集:

    //someparentpath/h3/somechildpath | //someparentpath/ul/li/div/somechildpath
    

    或者最后使用公共轴步骤的允许查询,这至少少了一点重复:

    (//someparentpath/h3 | //someparentpath/ul/li/div)/somechildpath
    
  • 使用一些 descending-or-self -hack 和 harpo 和 JLRishe 提出的谓词,但它们都有一个共同点,即您可能匹配的元素比您想要的要多。

我认为您可以得到的最接近的如下:

//someparentpath//*[self::h3 or self::div[parent::li/parent::ul]]/somechildpath

然而,正如 harpo 已经提到的,//阻止它们完全等同,我认为在单个表达式中没有办法解决这个问题。请注意,如果您正在使用 XSLT,则可以使用多个变量赋值来实现您尝试执行的操作并避免某些冗余部分:

<xsl:variable name="ppath" select="//someparentpath" />
<xsl:variable name="children" select="($ppath/h3 | $ppath/ul/div/li)/somechildpath" />

请注意,您描述的假设表达式:

//someparentpath/(h3 | ul/li/div)/somechildpath

XPath 2.0 中是允许的。在 XPath 1.0 中根本不允许这样做,因为 1.0 不允许在路径中途使用表达式。

好问题,我对"为什么"自己感兴趣。

不过,实际上

,您可以重写它

//someparentpath/(h3 | ul/li/div)/somechildpath

因为这个(不完全等同)

//someparentpath//*[self::h3 or self::ul/li/div]/somechildpath

这还不算太糟糕。

但是,是的,我对此感到沮丧。

最新更新