Bagaimana cara menggunakan XPath berisi () di sini?


142

Saya mencoba mempelajari XPath. Saya melihat contains()contoh lain di sekitar sini, tetapi tidak ada yang menggunakan operator DAN . Saya tidak bisa mengaktifkan ini:

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

Di:

...
<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>
...

ini bekerja untuk saya, saya mengujinya di whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm
— mihi

Jawaban:


199

Anda hanya melihat lianak pertama dalam kueri yang Anda miliki alih-alih mencari lielemen anak apa pun yang mungkin berisi teks 'Model',. Yang Anda butuhkan adalah kueri seperti berikut:

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

Query ini akan memberikan unsur-unsur yang memiliki classdari featureListdengan satu atau lebih lianak yang mengandung teks, 'Model'.


13
+1 - "./" agak menyesatkan - ini menunjukkan bahwa apa pun selain simpul saat ini akan diperhitungkan ketika Anda meninggalkannya, tetapi sebenarnya itu berlebihan: "// ul [@ class = ' featureList 'dan li [berisi (.,' Model ')]] "adalah hal yang sama.
— Tomalak

4
Yup, saya hanya spesifik. Mungkin sangat spesifik.
— Jeff Yates

Jika tidak ada lidengan Modeldalam ul, maka andkondisinya akan gagal. Jadi andkondisinya kembali falsepada set kosong, apakah itu benar?
— damluar

58

Saya sudah memberi +1 saya untuk solusi Jeff Yates.

Berikut ini penjelasan singkat mengapa pendekatan Anda tidak berhasil. Ini:

// ul [@ class = 'featureList' dan berisi (li, 'Model')]

menemukan batasan contains()fungsi (atau fungsi string lainnya di XPath, dalam hal ini).

Argumen pertama seharusnya berupa string. Jika Anda memberinya daftar simpul (memberinya " li" melakukannya), konversi ke string harus dilakukan. Tetapi konversi ini dilakukan untuk simpul pertama dalam daftar saja.

Dalam kasus Anda, simpul pertama dalam daftar adalah <li><b>Type:</b> Clip Fan</li>(dikonversi menjadi string: " Type: Clip Fan") yang berarti bahwa ini:

// ul [@ class = 'featureList' dan berisi (li, 'Type')]

akan benar-benar memilih simpul!


1
yang bagus telah berjuang untuk mencari tahu mengapa pertanyaan seperti: ".//td[contains(.//*,'something ')]" hanya bekerja hingga kedalaman 1. Saya sudah menemukan cara untuk membuatnya bekerja tetapi tidak yakin bagaimana cara di atas bekerja sama sekali. Apa yang sebenarnya saya butuhkan adalah ".//td[.//*[contains(., sesuatu ')]]"
— JonnyRaa

11

Ini adalah jawaban baru untuk pertanyaan lama tentang kesalahpahaman umum tentang contains()di XPath ...

Ringkasan: contains()berarti berisi substring , tidak mengandung simpul .

Penjelasan detail

XPath ini sering disalahartikan:

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

Interpretasi yang salah: Pilih yang ulunsur-unsur yang mengandung sebuah lielemen dengan Modeldi dalamnya.

Ini salah karena

  1. contains(x,y)berharap xmenjadi string, dan
  2. aturan XPath untuk mengonversi beberapa elemen menjadi string adalah ini :

    Node-set dikonversi ke string dengan mengembalikan nilai -string dari node dalam node-set yang pertama kali dalam urutan dokumen . Jika set simpul kosong, string kosong dikembalikan.

Interpretasi yang tepat: Pilih orang-orang ulelemen yang pertama li anak memiliki tali-nilai yang mengandung suatu Modelsubstring.

Contohnya

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> 

XPaths

  • //ul[contains(li, 'Model')]memilih one ulelemen.

    Catatan: The two ulElemen tidak dipilih karena string-nilai yang pertama lianak dari two uladalah Foo, yang tidak mengandung Modelsubstring.

  • //ul[li[contains(.,'Model')]]memilih elemen onedan two ul.

    Catatan: Kedua ulelemen dipilih karena contains()diterapkan ke masing li- masing individu. (Dengan demikian, aturan konversi multi-elemen-ke-string yang rumit dihindari.) Kedua ulelemen memang memiliki lianak yang nilai stringnya mengandung Modelsubstring - posisi lielemen tidak lagi penting.

Lihat juga


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

-5

Rekatkan containscontoh saya di sini:

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

2
Tidak ada nilai tableelemen atau EC_resultkelas dalam kode OP. Jawaban ini tidak masuk akal di sini dan harus dihapus.
— kjhughes
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.