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


Я хочу выбрать только класс сам по себе называется .дата

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

@$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 75

6 ответов:

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

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

The CSS селектор:

.foo

будет выбрать любой элемент, который имеет класс фу.

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

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

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

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

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

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

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

*[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/

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

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

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

пример:

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

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


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

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

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

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

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

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

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

ОСТЕРЕГАЙТЕСЬ ЗНАКОВ МИНУСА В ШАБЛОНЕ !!! Если вы запрашиваете "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.