Làm thế nào để sử dụng XPath chứa () ở đây?


142

Tôi đang cố gắng học XPath. Tôi đã xem xét các contains()ví dụ khác quanh đây, nhưng không có gì sử dụng toán tử AND . Tôi không thể làm việc này:

//ul[@class='featureList' and contains(li, 'Model')]

Trên:

...
<ul class="featureList">

<li><b>Type:</b> Clip Fan</li><li><b>Feature:</b> Air Moved: 65 ft.
    Amps: 1.1
    Clip: Grips any surface up to 1.63"
    Plug: 3 prong grounded plug on heavy duty model
    Usage: Garage, Workshop, Dorm, Work-out room, Deck, Office & more.</li><li><b>Speed Setting:</b> 2 speeds</li><li><b>Color:</b> Black</li><li><b>Power Consumption:</b> 62 W</li><li><b>Height:</b> 14.5"</li><li><b>Width:</b> Grill Diameter: 9.5"</li><li><b>Length:</b> 11.5"</li>

<li><b>Model #: </b>CR1-0081-06</li>
<li><b>Item #: </b>N82E16896817007</li>
<li><b>Return Policy: </b></li>
</ul>
...

cái này hiệu quả với tôi, tôi đã thử nó trên whitebeam.org/l Library / guide / TechNotes / xpathtestbed.rhtm
mihi

Câu trả lời:


199

Bạn chỉ nhìn vào liđứa trẻ đầu tiên trong truy vấn bạn có thay vì tìm kiếm bất kỳ liphần tử con nào có thể chứa văn bản , 'Model'. Những gì bạn cần là một truy vấn như sau:

//ul[@class='featureList' and ./li[contains(.,'Model')]]

Truy vấn này sẽ cung cấp cho bạn các yếu tố đó có một classsố featureListvới một hoặc nhiều litrẻ em có chứa các văn bản, 'Model'.


13
+1 - "./" là một chút sai lệch - nó gợi ý rằng mọi thứ khác ngoài nút hiện tại sẽ được tính đến khi bạn rời khỏi nó, nhưng thực tế nó là dư thừa: "// ul [@ class = ' FeatureList 'và li [chứa (.,' Model ')]] "là cùng một thứ.
Tomalak

4
Yup, tôi chỉ là cụ thể. Khá có thể quá cụ thể.
Jeff Yates

Nếu không có là livới Modeltrong ul, sau đó các andđiều kiện sẽ thất bại. Vì vậy, andđiều kiện trả falsevề tập hợp trống, nó có đúng không?
damluar

58

Tôi đã đưa +1 của mình cho giải pháp của Jeff Yates.

Dưới đây là một lời giải thích nhanh chóng tại sao phương pháp của bạn không hiệu quả. Điều này:

// ul [@ class = 'FeatureList' và chứa (li, 'Model')]

gặp phải giới hạn của contains()hàm (hoặc bất kỳ hàm chuỗi nào khác trong XPath, đối với vấn đề đó).

Đối số đầu tiên được cho là một chuỗi. Nếu bạn cung cấp cho nó một danh sách nút (cho nó " li" thực hiện điều đó), một chuyển đổi thành chuỗi phải diễn ra. Nhưng việc chuyển đổi này chỉ được thực hiện cho nút đầu tiên trong danh sách.

Trong trường hợp của bạn, nút đầu tiên trong danh sách là <li><b>Type:</b> Clip Fan</li>(được chuyển đổi thành một chuỗi: " Type: Clip Fan") có nghĩa là:

// ul [@ class = 'FeatureList' và chứa (li, 'Loại')]

thực sự sẽ chọn một nút!


1
một người tốt đã đấu tranh để tìm ra lý do tại sao các truy vấn như: ".//td[contains(.//*,'s Something ')]" chỉ hoạt động ở độ sâu 1. Tôi đã tìm ra cách để làm cho nó hoạt động nhưng không chắc chắn làm thế nào ở trên đã làm việc ở tất cả. Điều tôi thực sự cần là ".//td[.//*[contains(.,'s Something ')]]"
JonnyRaa

11

Đây là một câu trả lời mới cho một câu hỏi cũ về một quan niệm sai lầm phổ biến về contains()XPath ...

Tóm tắt: contains()có nghĩa là chứa một chuỗi con , không chứa một nút .

Giải thích chi tiết

XPath này thường bị hiểu sai:

//ul[contains(li, 'Model')]

Giải thích sai: Chọn những ulphần tử có chứa một liphần tử Modeltrong đó.

Điều này là sai bởi vì

  1. contains(x,y)mong đợi xlà một chuỗi, và
  2. sự cai trị XPath để chuyển đổi nhiều yếu tố để một chuỗi là này :

    Một tập hợp nút được chuyển đổi thành một chuỗi bằng cách trả về giá trị chuỗi của nút trong tập hợp nút đầu tiên theo thứ tự tài liệu . Nếu tập hợp nút trống, một chuỗi trống được trả về.

Ngay giải thích: Chọn những ulyếu tố mà đầu tiên li con có một chuỗi giá trịchứa một Modelchuỗi con.

Ví dụ

XML

<r>
  <ul id="one">
    <li>Model A</li>
    <li>Foo</li>
  </ul>
  <ul id="two">
    <li>Foo</li>
    <li>Model A</li>
  </ul>
</r> 

XPath

  • //ul[contains(li, 'Model')]chọn one ulphần tử.

    Lưu ý: Phần two ultử không được chọn vì giá trị chuỗi của licon đầu tiên two ulFoo, không chứa Modelchuỗi con.

  • //ul[li[contains(.,'Model')]]chọn onetwo ulcác yếu tố.

    Lưu ý: Cả hai ulyếu tố được chọn vì contains()được áp dụng cho từng licá nhân. (Do đó, quy tắc chuyển đổi nhiều thành phần thành chuỗi khó tránh được.) Cả hai ulphần tử đều có một licon có giá trị chuỗi chứa Modelchuỗi con - vị trí của liphần tử không còn quan trọng nữa.

Xem thêm


-2
//ul[@class="featureList" and li//text()[contains(., "Model")]]

-5

Dán containsví dụ của tôi ở đây:

//table[contains(@class, "EC_result")]/tbody

2
Không có tablephần tử hoặc EC_resultgiá trị lớp trong mã của OP. Câu trả lời này không có ý nghĩa ở đây và nên được xóa.
kjhughes
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.