Як використовувати XPath містить () тут?


142

Я намагаюся навчитися XPath. Я переглянув інші contains()приклади тут, але нічого, що використовує оператор AND . Я не можу це зробити так:

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

Увімкнено:

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

це працює для мене, я перевірив це на whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm
mihi

Відповіді:


199

Ви дивіться тільки на перший liдитина в запиті у вас є замість того , щоб шукати для будь-якого liдочірнього елемента , який може містити текст, 'Model'. Вам потрібен такий запит:

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

Цей запит дасть вам елементи , які мають classвід featureListоднієї або декількох liдітей , які містять текст, 'Model'.


13
+1 -. featureList 'і li [містить (.,' Модель ')]] "- це те саме.
Томалак

4
Так, я був просто конкретним. Цілком можливо занадто специфічні.
Джефф Йейтс

Якщо немає liз Modelін ul, то andумова не вдасться. Отже, andумова повертається falseна порожній множині, чи правильно?
damluar

58

Я вже дав свій +1 рішенням Джеффа Йейтса.

Ось коротке пояснення, чому ваш підхід не працює. Це:

// ul [@ class = 'featureList' і містить (li, 'Model')]

стикається з обмеженням contains()функції (або будь-якої іншої рядкової функції в XPath для цього питання).

Перший аргумент повинен бути рядком. Якщо ви подаєте йому список вузлів (надаючи це " li" це робить), повинно відбутися перетворення в рядок. Але це перетворення робиться лише для першого вузла у списку.

У вашому випадку перший вузол у списку <li><b>Type:</b> Clip Fan</li>(перетворений у рядок: " Type: Clip Fan"), що означає, що це:

// ul [@ class = 'featureList' і містить (li, 'Type')]

насправді вибрав би вузол!


1
приємно один намагався розібратися, чому запити типу: ".//td evidencecontains(.//*, щось щось)]]" працюють лише на глибину 1. Я зрозумів, як змусити його працювати, але хіба не був впевнений, як вище це взагалі працювало. Те, що мені насправді було потрібно, - ".//td снимки.//* evidencecontains(.,'something ')]]"
JonnyRaa

11

Це нова відповідь на старе запитання про поширене неправильне уявлення про contains()XPath ...

Підсумок: contains()засіб містить підрядку , а не містить вузол .

Детальне пояснення

Цей XPath часто трактується неправильно:

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

Неправильна інтерпретація: виберіть ті ulелементи, які містять у собі liелемент Model.

Це неправильно, тому що

  1. contains(x,y)очікує, xщо буде рядок і
  2. правило XPath для перетворення декількох елементів в рядку є це :

    Набір вузлів перетворюється на рядок шляхом повернення значення рядка вузла в наборі вузлів, який є першим у порядку документа . Якщо набір вузлів порожній, повертається порожня рядок.

Право інтерпретації: Виберіть ті ulелементи, перший li дитина має значення рядка , що містить в Modelподстроку.

Приклади

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')]вибирає one ulелемент.

    Примітка:two ul елемент не обраний , тому що рядок-значення першого liдитини з two ulце Foo, який не містить Modelпідрядок.

  • //ul[li[contains(.,'Model')]]вибирає елементи oneта two ulелементи.

    Примітка. Обидва ulелементи вибрані, оскільки contains()застосовуються до кожного liокремо. (Таким чином, уникнути складного правила перетворення декількох елементів у рядки.) Обидва ulелементи мають liдочірнє значення, значення рядка містить Modelпідрядку - положення liелемента вже не має значення.

Дивитися також



-5

Вставте мій containsприклад сюди:

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

2
У коді OP немає tableелемента або EC_resultзначення класу. Ця відповідь тут не має сенсу, і її слід видалити.
kjhughes
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.