Как использовать 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
в этом.
Это неправильно, потому что
contains(x,y)
надеетсяx
быть строкой, иправило 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
элемент больше не имеет значения.
Смотрите также
//ul[@class="featureList" and li//text()[contains(., "Model")]]
Вставь мой contains
пример здесь:
//table[contains(@class, "EC_result")]/tbody