แบบสอบถาม XPath เพื่อรับอินสแตนซ์ที่ n ขององค์ประกอบ


138

มีไฟล์ HTML (เนื้อหาที่ฉันไม่ได้ควบคุม) ที่มีinputองค์ประกอบหลายอย่างทั้งหมดที่มีidแอตทริบิวต์คงที่เหมือนกันของ"search_query". เนื้อหาของไฟล์สามารถเปลี่ยนแปลงได้ แต่ฉันรู้ว่าฉันต้องการรับinputองค์ประกอบที่สองที่มีแอตทริบิวต์ id "search_query"เสมอ

ฉันต้องการนิพจน์ XPath เพื่อทำสิ่งนี้ ฉันพยายาม//input[@id="search_query"][2]แล้วแต่ไม่ได้ผล นี่คือตัวอย่างสตริง XML ที่การสืบค้นนี้ล้มเหลว:

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

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

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

โปรดทราบว่าข้างต้นเป็นเพียงตัวอย่างและโค้ด HTML อื่น ๆ อาจแตกต่างกันมากและinputองค์ประกอบสามารถปรากฏได้ทุกที่โดยไม่มีโครงสร้างเอกสารที่สอดคล้องกัน (ยกเว้นว่าฉันรับประกันว่าจะมีอย่างน้อยสองinputองค์ประกอบที่มีแอตทริบิวต์ id ของ"search_query").

นิพจน์ XPath ที่ถูกต้องคืออะไร?


คำถามดี +1 ดูคำตอบของฉันสำหรับคำอธิบายที่สมบูรณ์เกี่ยวกับปัญหาและวิธีแก้ปัญหาที่ต้องการ
Dimitre Novatchev

8
ประเด็นรอง: คุณไม่ควรมีมากกว่าหนึ่งองค์ประกอบที่มี ID ที่กำหนด (ดังนั้น HTML ในคำถามจึงไม่ถูกต้อง) ในทางปฏิบัติเบราว์เซอร์จะให้คุณทำต่อไป แต่ถ้าคุณพลาดประโยชน์เพียงอย่างเดียวของการใช้ ID นั่นคือสัญญาณว่า "ฉันไม่เหมือนใคร" (ในขณะที่คลาสได้รับการออกแบบมาเพื่อใช้สำหรับสิ่งที่ไม่ใช่ - ตัวบ่งชี้เฉพาะ)
machineghost

คำตอบ:


256

นี่คือคำถามที่พบบ่อย :

//somexpression[$N]

หมายถึง "ค้นหาทุกโหนดที่เลือกโดย//somexpressionที่เป็น$Nลูกของพาเรนต์"

สิ่งที่คุณต้องการคือ :

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

ข้อควรจำ : ตัว[]ดำเนินการมีลำดับความสำคัญ (ลำดับความสำคัญ) สูงกว่า//ตัวย่อ


6
ฉันชอบคำตอบนี้ ฉันไม่ได้พิจารณาปัญหาลำดับความสำคัญ (ฉันแค่สันนิษฐานว่ามีลำดับความสำคัญจากซ้ายไปขวาอย่างง่าย)
rlandster

12
@rlandster: คำว่า "ลำดับความสำคัญ" อาจทำให้สับสน รูปแบบย่อของ//input[@id='search_query'][2]คือ:/descendat-or-self::node()/child::input[attribute::id='search_query'][position()=2]

23
สำหรับผู้ที่มาที่นี่จาก Google - การนับจะเริ่มตั้งแต่ 1 - [1] เป็นองค์ประกอบแรกเป็นต้น
ม.ค. มาเรส

แปลกที่ในการค้นหา XPath เหล่านี้อาร์เรย์ประเภทนี้เริ่มต้นด้วย 1 ทำให้ฉันสับสน
Ivotje50

@ Ivotje50 ใช่ลำดับ XPath และอาร์เรย์เป็นแบบ 1
Dimitre Novatchev

23

ดูเหมือนว่าจะได้ผล:

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

ฉันใช้สิ่งนี้จาก "XSLT 2.0 และ XPath 2.0 Programmer's Reference, 4th Edition" โดย Michael Kay

นอกจากนี้ยังมีหมายเหตุในส่วน "ไวยากรณ์แบบย่อ" ของข้อกำหนดภาษาเส้นทาง XML http://www.w3.org/TR/xpath/#path-abตัวย่อที่ให้เบาะแส


ขอบคุณมากสำหรับคำตอบนี้ ในกรณีของฉันวิธีแก้ปัญหาที่ยอมรับจะไม่ทำงานเนื่องจากฉันใช้ xpath ในกรอบงานหุ่นยนต์ซึ่งจะไม่ยอมรับเส้นทางที่เริ่มต้นด้วยวงเล็บ อย่างไรก็ตามสิ่งนี้ควรทำตามเคล็ดลับ
dahui
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.