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

时间:2014-02-13 04:28:36

标签: xpath

这有效:

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

这不是:(为什么?

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

3 个答案:

答案 0 :(得分:9)

XPath 1.0的语法不允许在轴步骤中进行更改,请参阅specifications for node sets或尝试XPath 1.0 Grammar Test Page。语法允许您的第一个查询,第二个查询没有有效的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提出的谓词,但它们的共同点是你可能匹配的元素多于你想要的。

答案 1 :(得分:3)

我认为你能得到的最接近的是:

//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不允许你在路径的中途使用表达式。

答案 2 :(得分:0)

好问题,我对自己的“为什么”感兴趣。

但实际上,你可以改写这个

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

这个(不太相同)

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

这不是太糟糕了。

但是,我对此感到沮丧。