xpath'或'表示与xmllib2的联合('|')

时间:2010-08-16 14:39:26

标签: xpath union libxml2

我有XML文档,如:

<rootelement>
<myelement>test1</myelement>
<myelement>test2</myelement>
<myelement type='specific'>test3</myelement>
</rootelement>

我想检索特定的myelement如果它不存在,然后第一个。所以我写道:

/rootelement/myelement[@type='specific' or position()=1]

关于'或表达'的XPath spec状态:

  

如果是,则不评估右操作数   左操作数计算结果为真

问题是libxml2-2.6.26似乎应用了两个表达式的并集,返回“2节点集”(例如使用xmllint --shell)。

是libxml2还是我做错了什么?

2 个答案:

答案 0 :(得分:10)

简短回答:你的选择器不能表达你的想法。


or运算符 是一个联盟。

您引用的规范部分(“右侧操作数未评估...”)是标准boolean logic short circuiting的一部分。

这就是为什么你为你的示例输入获得一个2节点集的原因:XPath查看myelement的每个rootelement,并将[@type='specific' or position()=1]部分应用于每个这样的节点确定它是否与选择器匹配。

  1. <myelement>test1</myelement>@type='specific'不匹配,但它与position()=1匹配,因此它与整个选择器匹配。
  2. <myelement>test2</myelement>@type='specific'不匹配,且与position()=1不匹配,因此与整个选择器不匹配。
  3. <myelement type='specific'>test3</myelement>匹配@type='specific'(因此XPath不必测试其位置 - 这是短路部分),因此它匹配整个选择器。
  4. 第一个和最后一个<myelement>匹配整个选择器,因此返回一个2节点集。

    以您希望的方式选择元素的最简单方法是分两步完成。这是伪代码(我不知道你实际使用XPath的上下文,我对编写XPath语法选择器并不熟悉):

    1. 选择与elements
    2. 匹配的/rootelement/myelement[@type='specific']
    3. 如果elements为空,请选择与elements
    4. 匹配的/rootelement/myelement[position()=1]

答案 1 :(得分:7)

@Matt Ball很好地解释了你的问题的原因。

这是一个XPath单线选择你想要的

/*/myelement[@type='specific'] | /*[not(myelement[@type='specific'])]/myelement[1]