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

116

Я пытаюсь изучить 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>
...
Теги:
xpath

4 ответа

163
Лучший ответ

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

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

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

  • 12
    +1 - «./» немного вводит в заблуждение - это говорит о том, что что-либо, кроме текущего узла, будет учтено, когда вы его пропустите, но на самом деле это избыточно: «// ul [@ class = ' featureList 'и li [содержит (.,' Модель ')]] "это то же самое.
  • 4
    Да, я просто был конкретным. Вполне возможно, слишком конкретным.
Показать ещё 1 комментарий
53

Я уже отдал свое решение +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!

  • 1
    один из них пытался выяснить, почему такие запросы, как: ".//td[contains(.//* ,'something ')]" работают только на глубину 1. Я понял, как заставить это работать, но не смог уверен, как выше работает вообще. На самом деле мне нужно было ".//td[.//*[contains( .,'something ')]]"
1

Это новый ответ на старый вопрос о распространенном заблуждении о contains() в XPath...

Сводка: contains() означает, что содержит подстроку, не содержит node.

Подробное объяснение

Этот XPath часто неверно интерпретируется:

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

Неверная интерпретация: Выберите те элементы ul, которые содержат элемент li с Model в нем.

Это неправильно, потому что

  • contains(x,y) ожидает, что x будет строкой, а
  • Правило XPath для преобразования нескольких элементов в строку this:

    A node -set преобразуется в строку, возвращая string-value of node в node -set, который сначала находится в порядок документа. Если node -set пуст, возвращается пустая строка.

Правильная интерпретация: Выберите те элементы 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

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

//table[contains(@class, "EC_result")]/tbody
  • 0
    В EC_result OP нет элемента table или EC_result класса EC_result . Этот ответ не имеет смысла здесь и должен быть удален.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню