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>
...
ryeguy
sumber
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'.

Jeff Yates
sumber
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!

Tomalak
sumber
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

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

Rekatkan containscontoh saya di sini:

//table[contains(@class, "EC_result")]/tbody
hahakubile
sumber
2
Tidak ada nilai tableelemen atau EC_resultkelas dalam kode OP. Jawaban ini tidak masuk akal di sini dan harus dihapus.
kjhughes