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


300

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

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

Answers:


444

采用:

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

这将首先获得具有location属性等于'US'的书籍元素。然后它将从该集合中选择第一个节点。注意某些实现需要使用括号。

请注意,这与/bookstore/book[1][@location='US']除非第一个元素碰巧具有该location属性是不同的。


如何为// bookstore / book [@ location ='US']做同样的事情?
亚历山大·伊林

7
这将从“美国”获得所有书籍。(/ bookstore / book [@ location ='US'])[1]将获得第一个。
凯文·德瑞杰

3
@KevinDriedger /bookstore/book[@location='US'][1]不会返回“ US”中的所有书籍。我已经多次测试了它,并且使用了不同语言的xpath实现。/bookstore/book[@location='US'][1]返回书店下的第一本“美国”书。如果有多个书店,那么它将从每个书店返回第一个。这就是OP要求的(书店下的第一个节点)。您的版本仅返回所有书店中的一本书(第一个匹配项)。
Jonathan Fingland'4

3
@JonathanFingland您误解了-再次阅读KevinDriedger的答案以及AlexanderV.Ilyin的问题。你们都是同一回事。
kiedysktos '16

175

/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]预期工作。


11
此处接受答案的作者。OP的问题被认为是/bookstore/book[1]而不是(/bookstore/book)[1]。您提供的案例与所请求的一个OP不同。大概OP接受了我的回答,因为它做了他所期望的(并要求)。
乔纳森·芬兰

提供的答案有助于我解决这个特殊的情况。有人可以解释为什么它不能处理“更复杂的情况”吗?因为基本上它确实找到了包含两个项目的列表,所以[2]应该就可以了(在我的世界中)
Skurpi,2012年

我还发现此答案比所选答案更正确,因为在我的情况下,我还具有更复杂的结构,只需添加[1]即可返回多个节点。谢谢!
mydoghasworms 2012年

2
括号有效!您也可以在(..)[1]之后添加更多路径,例如:'(//div[text() = "'+ name +'"])[1]/following-sibling::*/div/text()'。如果有许多匹配的节点name
Hlung 2012年

1
我正在改变看法。经过一段距离后,我明白了这个答案在说什么,如果我没有看到OP的示例,我会投赞成票。我想我对这个答案的语气有反应。如果@tkurki解释了更多有关将条件与选择第一个节点分开的内容,我会立即看到它。对于JonFingland来说可能也是一样。
Gerard ONeill

51

作为对乔纳森·芬德兰(Jonathan Fingland)答案的解释:

  • 同一谓词([position()=1 and @location='US'])中的多个条件必须整体上为真
  • 连续谓词([position()=1][@location='US'])中的多个条件必须一个接一个地成立
  • 这意味着[position()=1][@location='US']!= [@location='US'][position()=1]
    [position()=1 and @location='US']==[@location='US' and position()=1]
  • 提示:一个人[position()=1]可以缩写为[1]

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


15

考虑到更复杂的结构化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]


10
    <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]

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

直接回答:

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

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

顺便说一句,如果您想在此示例中查找第一本不是书店直接子书的美国图书:

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

4

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

例如:

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

您可以提供所需的节点号。


2

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

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


-1

借助在线xpath测试仪,我正在编写此答案...
为此:

<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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.