首页 > 解决方案 > xpath 中的否定 - 随之而来的是欢闹

问题描述

最近我在几个方面遇到了 xpath 问题(可能是未来问题的素材);但是我研究得越多,我就越相信问题的一部分是我并没有真正理解否定在 xpath 中是如何工作的。

假设我们得到了这个:

<teams>
   <team>
     <title>My Own Baseball Team</title>
       <player name="Abbot" position="first_base" />
       <player name="Costello" position="second_base"  />
     <location>Here</location>
   </team>
</teams>

让我们运行一些健全性检查:

count(//*)

输出是6。正确的。

有多少玩家?

count(//*[name()="player"])

输出是2。再更正。

有多少非玩家?为了安全起见,让我们以 3 种不同的方式询问它:

count(//*[not(name()="player")])
count(//*[name()!="player"])
count(//*[name() ne "player"])

输出总是4; 有道理 - 6 个元素,2 个玩家 - 所以 4 个非玩家。

就这样了解我们的方位,谁是非玩家?

//*[name() != "player"]/name()

输出:

teams
team
title
location

现在我们知道了。因此,让我们从旧的 Abbot & Costello 例程中借用一个问题。在球员中,谁排在第二位?

//*[name()= "player"][2]/@name

输出是Costello。又对了。

在 4 名非球员中,谁排在第三位?

//*[name() != "player"][3]

不匹配!无论您如何否定,答案都是相同的。

什么?我们之前确定我们有 4 个非玩家 - 为什么没有人在第三?回溯,让我们看看谁先上,这次明确:

//*[not(name() = "player")][position()=1]/name()

输出:

teams
team
title

又是什么?4个非玩家中有3个先上?在那种情况下,第四个非玩家必须在第二个,对吧?

//*[name() ne "player"][position()=2]/name()

输出是location。这样更好,不是吗?那么location在非玩家中是最后一个吗?

//*[name() != "player"][position()=last()]/name()

输出比 A&C 更像是《爱丽丝梦游仙境》:

teams
team
location

所以这就是我放弃的地方——这对我来说不再有意义。

为什么会这样?您将如何制定查询,例如“在什么非玩家位置可以location找到”问题的答案是4

标签: xmlxpath

解决方案


问题始于对 XPath 含义的普遍误解:

//*[name() != "player"][3]

不代表,选择第三个非玩家;这意味着,从非玩家中选择那些是其各自父母的第三个孩子的人。(正如你所发现的,没有这样的非玩家元素。)

如果要选择所有非玩家元素中的第三个,请使用

( 括号内的非玩家 XPath 之一 )[3]

也可以看看


推荐阅读