Как использовать 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>
...

Ответ 1

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

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

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

Ответ 2

Я уже отдал свое решение +1 Джеффу Ятес.

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

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

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

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

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

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

действительно выберет node!

Ответ 3

Это новый ответ на старый вопрос о распространенном заблуждении о 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 больше не имеет значения.

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

Ответ 4

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

Ответ 5

Вставьте сюда пример contains:

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