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

fou*_*fou 6 union xpath libxml2

我有XML文档,如:

<rootelement>
<myelement>test1</myelement>
<myelement>test2</myelement>
<myelement type='specific'>test3</myelement>
</rootelement>
Run Code Online (Sandbox Code Playgroud)

我想检索具体的myelement,如果它不存在,那么第一个.所以我写道:

/rootelement/myelement[@type='specific' or position()=1]
Run Code Online (Sandbox Code Playgroud)

XPath的规范对"或表达"各国:

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

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

它是libxml2还是我做错了什么?

Mat*_*all 10

简短的回答:你的选择器没有表达你的想法.


or运营商一个工会.

您引用的规范部分("右侧操作数未评估...")是标准布尔逻辑短路的一部分.

这就是为什么你为你的示例输入获得一个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不必测试其位置 - 这是短路部分),因此它匹配整个选择器.

第一个和最后<myelement>一个匹配整个选择器,因此它返回一个2节点集.

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

  1. 选择elements那个匹配/rootelement/myelement[@type='specific']
  2. 如果elements为空,请选择elements该匹配项/rootelement/myelement[position()=1]


Dim*_*hev 7

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

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

/*/myelement[@type='specific'] | /*[not(myelement[@type='specific'])]/myelement[1] 
Run Code Online (Sandbox Code Playgroud)