Как использовать XPath содержит () здесь?

Я пытаюсь выучить 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>
...

4 ответа

Решение

Вы смотрите только на первое li ребенок в запросе у вас вместо того, чтобы искать любой li дочерний элемент, который может содержать текст, 'Model', Вам нужен запрос, подобный следующему:

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

Этот запрос даст вам элементы, которые имеют class из featureList с одним или несколькими li дети, которые содержат текст, 'Model',

Я уже дал +1 к решению Джеффа Йейтса.

Вот краткое объяснение, почему ваш подход не работает. Это:

// ul [@ class = 'featureList' и содержит (li, 'Model')]

сталкивается с ограничением contains() функция (или любая другая строковая функция в XPath, в этом отношении).

Первый аргумент должен быть строкой. Если вы кормите его список узлов (давая его "li"делает это), необходимо выполнить преобразование в строку. Но это преобразование выполняется только для первого узла в списке.

В вашем случае первый узел в списке <li><b>Type:</b> Clip Fan</li> (преобразовано в строку: "Type: Clip Fan"), что означает, что это:

// ul [@ class = 'featureList' и содержит (li, 'Type')]

будет на самом деле выбрать узел!

Это новый ответ на старый вопрос о распространенном заблуждении о 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')] выбирает oneul элемент.

    Примечание: twoul элемент не выбран, потому что строковое значение первого li дитя twoul является Foo, который не содержит Model подстрока.

  • //ul[li[contains(.,'Model')]] выбирает one а также twoul элементы.

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

Смотрите также

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

Вставь мой contains пример здесь:

//table[contains(@class, "EC_result")]/tbody
Другие вопросы по тегам