Выбор класса css с помощью xpath - PullRequest
78 голосов
/ 10 января 2012

Я хочу выбрать только отдельный класс с именем .date

По какой-то причине я не могу заставить это работать. Если кто-нибудь знает, что не так с моим кодом, он будет очень признателен.

@$doc = new DOMDocument();
@$doc->loadHTML($html);
$xml = simplexml_import_dom($doc); // just to make xpath more simple
$images = $xml->xpath('//[@class="date"]');                             
foreach ($images as $img)
{
    echo  $img." ";
}

Ответы [ 6 ]

229 голосов
/ 03 февраля 2012

Я хочу написать канонический ответ на этот вопрос, потому что у ответа выше есть проблема.

Наша проблема

Селектор CSS :

.foo

выберет любой элемент, имеющий класс foo .

Как вы делаете это в XPath?

Хотя XPath является более мощным, чем CSS, XPath не имеет собственного эквивалента селектора класса CSS . Тем не менее, есть решение.

Правильный способ сделать это

Эквивалентный селектор в XPath :

//*[contains(concat(" ", normalize-space(@class), " "), " foo ")]

Функция normalize-space удаляет начальные и конечные пробелы (а также заменяет последовательности пробельных символов одним пробелом).

(в более общем смысле) это также эквивалент селектора CSS:

*[class~="foo"]

, который будет соответствовать любому элементу, чье значение атрибута class является списком разделенных пробелами значений, одно из которых точно равно foo .

Несколько очевидных, но неправильных способов сделать это

Селектор XPath:

//*[@class="foo"]

не работает! потому что он не будет соответствовать элементу, который имеет более одного класса, например

<div class="foo bar">

Он также не будет совпадать, если вокруг имени класса есть лишние пробелы:

<div class="  foo ">

«Улучшенный» XPath-селектор

//*[contains(@class, "foo")]

тоже не работает! потому что он неправильно сопоставляет элементы с классом foobar , например

<div class="foobar">

Благодарность идет этому парню, который был первым опубликованным решением этой проблемы, которое я нашел в Интернете: http://dubinko.info/blog/2007/10/01/simple-parsing-of-space-seprated-attributes-in-xpathxslt/

10 голосов
/ 10 января 2012

//[@class="date"] не является допустимым xpath.

Попробуйте //*[@class="date"], или, если вы знаете, что это изображение, //img[@class="date"]

7 голосов
/ 13 декабря 2016

XPath 3.1 представляет функцию содержит токен и, таким образом, наконец решает это "официально". Он предназначен для поддержки классов .

Пример:

//*[contains-token(@class, "foo")]

Эта функция обеспечивает правильную обработку пробелов (не только (U + 0020)), работает в случае повторения имени класса и, как правило, охватывает крайние случаи.


Примечание: На сегодняшний день (2016-12-13) XPath 3.1 имеет статус Рекомендация кандидата .

3 голосов
/ 09 марта 2016

В XPath 2.0 вы можете:

//*[count(index-of(tokenize(@class, '\s+' ), 'foo')) = 1]

как сказано Кристианом Вайске в: https://cweiske.de/tagebuch/XPath%3A%20Select%20element%20by%20class.htm

1 голос
/ 30 апреля 2015

ВНИМАНИЕ МИНУСНЫХ ЗНАКОВ В ШАБЛОНЕ !!!Если вы запрашиваете «мой собственный класс» в DOM:

<ul class="my-ownclass"><li>...</li></ul>
<ul class="someother"><li>...</li></ul>
<ul><li>...</li></ul>

$finder = new DomXPath($dom);
$nodes = $finder->query(".//ul[contains(@class, 'my-ownclass')]"); // This will NOT behave as expected! This will strangely match all the <ul> elements in DOM.
$nodes = $finder->query(".//ul[contains(@class, 'ownclass')]"); // This will match the element.
1 голос
/ 13 июня 2012

HTML позволяет вводить имена элементов и атрибутов без учета регистра, а затем класс - это список имен классов, разделенных пробелами Здесь мы идем для тега img и class с именем date:

//*['IMG' = translate(name(.), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')]/@*['CLASS' = translate(name(.), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') and contains(concat(' ', normalize-space(.), ' '), concat(' ', 'date', ' '))]

См. Также: Преобразователь селектора CSS в XPath

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...