ChatGPT解决这个技术问题 Extra ChatGPT

如何使用 XPath 选择具有特定属性的第一个元素

XPath bookstore/book[1] 选择 bookstore 下的第一个书节点。

如何选择匹配更复杂条件的第一个节点,例如匹配 /bookstore/book[@location='US'] 的第一个节点


t
the Tin Man

利用:

(/bookstore/book[@location='US'])[1]

这将首先获取位置属性等于“US”的 book 元素。然后它将从该集合中选择第一个节点。请注意括号的使用,这是某些实现所必需的。

请注意,这与 /bookstore/book[1][@location='US'] 不同,除非第一个元素也恰好具有该位置属性。


我怎么能为 //bookstore/book[@location='US'] 做同样的事情?
这将从“美国”获得所有书籍。 (/bookstore/book[@location='US'])[1] 将获得第一个。
@KevinDriedger /bookstore/book[@location='US'][1] 不会退回所有来自“美国”的书籍。我已经在不同语言的 xpath 实现下对其进行了多次测试。 /bookstore/book[@location='US'][1] 返回书店下的第一本“美国”图书。如果有多个书店,那么它将返回每个书店的第一个。这是 OP 要求的(书店下的第一个节点)。您的版本仅返回所有书店中的一本书(第一场比赛)。
@JonathanFingland 你误解了 - 再次阅读 KevinDriedger 的回答,以及 AlexanderV.Ilyin 问题的上下文。你们俩的意思是一样的。
i
iliketocode

/bookstore/book[@location='US'][1] 仅适用于简单结构。

添加更多结构,事情就会中断。

和-

<bookstore>
 <category>
  <book location="US">A1</book>
  <book location="FIN">A2</book>
 </category>
 <category>
  <book location="FIN">B1</book>
  <book location="US">B2</book>
 </category>
</bookstore> 

/bookstore/category/book[@location='US'][1] 产量

<book location="US">A1</book>
<book location="US">B2</book>

不是“匹配更复杂条件的第一个节点”。 /bookstore/category/book[@location='US'][2] 不返回任何内容。

使用括号,您可以获得原始问题的结果:

(/bookstore/category/book[@location='US'])[1] 给出

<book location="US">A1</book>

(/bookstore/category/book[@location='US'])[2] 按预期工作。


此处接受的答案的作者。 OP 的问题是 /bookstore/book[1] 而不是 (/bookstore/book)[1]。您提供的案例与 OP 要求的案例不同。据推测,OP 接受了我的回答,因为它符合他的预期(和要求)。
提供的这个答案帮助我解决了这个特殊情况。有人可以解释为什么它不能处理“更复杂的情况”吗?因为基本上它确实找到了一个包含两个项目的列表,所以 [2] 应该把它捡起来(在我的世界里)
我还发现这个答案比选择的答案更正确,因为在我的情况下,我也有一个更复杂的结构,只需添加 [1] 即可返回多个节点。谢谢!
括号有效!您还可以在 (..)[1] 之后添加更多路径,例如:'(//div[text() = "'+ name +'"])[1]/following-sibling::*/div/text()'。如果有很多节点匹配 name
我正在改变我的看法。经过一段距离后,我得到了这个答案的意思,如果我没有看到 OP 的示例,我会投票赞成这个。我想我是对这个答案的语气做出反应;如果@tkurki 解释了更多关于将条件与第一个节点的选择分开的信息,我会立即看到它。 JonFingland 或许也是如此。
T
Tomalak

作为对乔纳森芬兰回答的解释:

同一谓词中的多个条件([position()=1 和 @location='US'])必须整体为真

连续谓词中的多个条件 ([position()=1][@location='US']) 必须一个接一个地为真

这意味着 [position()=1][@location='US'] != [@location='US'][position()=1] 而 [position()=1 and @location='US'] == [@location='US' 和 position()=1]

提示:一个单独的 [position()=1] 可以缩写为 [1]

您可以使用布尔运算符“and”和“or”以及布尔 XPath 函数 not()true()false() 在谓词中构建复杂的表达式。另外,您可以将子表达式包装在括号中。


是否可以在不使用多个“和”运算符的情况下拥有一组位置(如 [1,3,5:7,9])?
@M.HosseinRahimi 在 XPath 1.0 中,不。在 XPath 2.0 中,序列和 = 运算符起到了作用:[position() = (1,3,5,6,7,9)]
G
Gee-Bee

查找第一个英文书节点(在整个文档中)的最简单方法,考虑到更复杂的结构化 xml 文件,例如:

<bookstore>
 <category>
  <book location="US">A1</book>
  <book location="FIN">A2</book>
 </category>
 <category>
  <book location="FIN">B1</book>
  <book location="US">B2</book>
 </category>
</bookstore> 

是 xpath 表达式:

/descendant::book[@location='US'][1]


我不知道您为什么将“类别”添加到(假定的)xml 中。我对此投了反对票,因为它回答了 OP 没有提出的问题。
i
iZian
    <bookstore>
     <book location="US">A1</book>
     <category>
      <book location="US">B1</book>
      <book location="FIN">B2</book>
     </category>
     <section>
      <book location="FIN">C1</book>
      <book location="US">C2</book>
     </section>
    </bookstore> 

所以鉴于上述情况;你可以选择第一本书

(//book[@location='US'])[1]

这将找到第一个在美国有位置的地方。 [A1]

//book[@location='US']

将返回包含位置为 US 的所有书籍的节点集。 [A1,B1,C2]

(//category/book[@location='US'])[1]

将返回存在于文档任何位置的类别中的第一本书位置 US。 [B1]

(/bookstore//book[@location='US'])[1]

将返回存在于根元素 bookstore 下任何位置的第一本位置为 US 的书;确实使 /bookstore 部分变得多余。 [A1]

直接回答:

/bookstore/book[@location='US'][1]

将为您返回位于书店 [A1] 下的 US 位置的 book 元素的第一个节点

顺便说一句,如果你想,在这个例子中找到第一本不是书店直系子的美国书:

(/bookstore/*//book[@location='US'])[1]

我不知道您为什么将“类别”添加到(假定的)xml 中。我对此投了反对票,因为它回答了 OP 没有提出的问题。
@samwyse,因为 OP 没有提供更多关于源数据中其他信息的上下文。因此,您根据您认为他们的数据可能是什么样的回答,并提供更广泛的背景,以便 OP 和为相同和类似问题找到此问题的人可以使用实际示例了解更多信息。你会注意到我在书店下有一本书。与您的其他复制粘贴响应答案不同。
f
frianH

如果 xpath 复杂或存在多个具有相同 xpath 的节点,则使用索引获取所需的节点。

前任 :

(//bookstore[@location = 'US'])[index]

您可以给出所需节点的编号。


E
Ed Bangga

如果在给定的 xml 上提供了命名空间,最好使用它。

(/*[local-name() ='bookstore']/*[local-name()='book'][@location='US'])[1]

E
Exception_al

例如。

<input b="demo">

(input[@b='demo'])[1]

M
Mohsen Abasi

在在线 xpath tester 的帮助下,我正在写这个答案...
为此:

<table id="t2"><tbody>
<tr><td>123</td><td>other</td></tr>
<tr><td>foo</td><td>columns</td></tr>
<tr><td>bar</td><td>are</td></tr>
<tr><td>xyz</td><td>ignored</td></tr>
</tbody></table>

以下xpath:

id("t2") / tbody / tr / td[1]

输出:

123
foo
bar
xyz

由于 1 表示选择所有 td 元素,它们是它们自己的直接父级的第一个子元素。
但以下 xpath:

(id("t2") / tbody / tr / td)[1]

输出:

123