Truy vấn XPath để lấy phiên bản thứ n của một phần tử


134

Có một tệp HTML (có nội dung mà tôi không kiểm soát) có một số inputthành phần có cùng idthuộc tính cố định "search_query". Nội dung của tệp có thể thay đổi, nhưng tôi biết rằng tôi luôn muốn lấy inputphần tử thứ hai với thuộc tính id "search_query".

Tôi cần một biểu thức XPath để làm điều này. Tôi đã thử //input[@id="search_query"][2]nhưng không được. Dưới đây là một chuỗi XML mẫu trong đó truy vấn này không thành công:

<div>
  <form>
    <input id="search_query" />
   </form>
</div>

<div>
  <form>
    <input id="search_query" />
  </form>
</div>

<div>
  <form>
    <input id="search_query" />
  </form>
</div>

Hãy nhớ rằng ở trên chỉ là một ví dụ và mã HTML khác có thể khá khác nhau và các inputyếu tố có thể xuất hiện ở bất cứ đâu không có cấu trúc tài liệu nhất quán (ngoại trừ tôi được đảm bảo sẽ luôn có ít nhất hai inputyếu tố có thuộc tính id là "search_query").

Biểu thức XPath đúng là gì?


Câu hỏi hay, +1. Xem câu trả lời của tôi để được giải thích đầy đủ về vấn đề và giải pháp mong muốn.
Dimitre Novatchev

7
Điểm nhỏ: bạn không bao giờ nên có nhiều hơn một yếu tố với một ID nhất định (và do đó, HTML trong câu hỏi thực sự không hợp lệ). Trong thực tế, các trình duyệt sẽ cho phép bạn làm điều đó, nhưng nếu bạn bỏ lỡ lợi ích duy nhất của việc sử dụng ID, thì đó là tín hiệu "Tôi là duy nhất" (trong khi các lớp được thiết kế để không sử dụng chữ ký duy nhất).
máy vào

Câu trả lời:


244

Đây là một câu hỏi thường gặp :

//somexpression[$N]

có nghĩa là "Tìm mọi nút được chọn bởi //somexpressionđó là $Ncon thứ của cha mẹ".

Những gì bạn muốn là :

(//input[@id="search_query"])[2]

Ghi nhớ : []Toán tử có quyền ưu tiên (ưu tiên) cao hơn //chữ viết tắt.


6
Tôi thích câu trả lời này. Tôi đã không xem xét một vấn đề ưu tiên (tôi chỉ giả định ưu tiên từ trái sang phải đơn giản).
rlandster

10
@rlandster: Từ "ưu tiên" có thể gây nhầm lẫn. Hình thức không được viết tắt //input[@id='search_query'][2]là:/descendat-or-self::node()/child::input[attribute::id='search_query'][position()=2]

21
Đối với những người đến đây từ Google - việc đánh số bắt đầu từ 1 - [1] là yếu tố đầu tiên và cứ thế
Jan Mares

Điều kỳ lạ là trong các truy vấn XPath này, các loại mảng bắt đầu bằng 1, làm tôi bối rối.
Ivotje50

@ Ivotje50 Có trình tự và mảng XPath dựa trên 1
Dimitre Novatchev

21

Điều này dường như làm việc:

/descendant::input[@id="search_query"][2]

Tôi lấy cái này từ "Tham khảo của Lập trình viên XSLT 2.0 và XPath 2.0, Phiên bản thứ 4" của Michael Kay.

Ngoài ra còn có một ghi chú trong phần "Cú pháp viết tắt" của đặc tả Ngôn ngữ Đường dẫn XML http://www.w3.org/TR/xpath/#path-abenamev cung cấp manh mối.


Rất cám ơn cho câu trả lời này. Trong trường hợp của tôi, giải pháp được chấp nhận sẽ không hoạt động vì tôi đang sử dụng xpath trong khung robot, sẽ không chấp nhận các đường dẫn bắt đầu bằng dấu ngoặc. Điều này tuy nhiên, nên thực hiện các mẹo
dahui
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.