Выбор класса css с помощью xpath

Я хочу выбрать только класс по-своему .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." ";
}

Ответ 1

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

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

Селектор CSS:

.foo

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

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

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

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

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

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

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

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

*[class~="foo"]

который будет соответствовать любому элементу, значение атрибута класса которого представляет собой список значений, разделенных пробелами, один из которых точно равен 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- в-xpaспасибоslt/

Ответ 2

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

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

Ответ 3

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

Пример:

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

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


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

Ответ 5

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

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

Смотрите также: Селектор CSS для преобразования XPath

Ответ 6

ОГРАНИЧИВАЯ МИНУСЫ В ШАБЛОНЕ!!! Если вы запрашиваете "my-ownclass" в 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.