选择带有xpath的css类

时间:2012-01-10 19:00:43

标签: php html xml xpath web

我想只选择一个名为.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 个答案:

答案 0 :(得分:229)

我想写这个问题的规范答案,因为上面的答案有问题。

我们的问题

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-in-xpathxslt/

答案 1 :(得分:9)

//[@class="date"]不是有效的xpath。

尝试//*[@class="date"],或者如果你知道它是图片,//img[@class="date"]

答案 2 :(得分:7)

XPath 3.1 引入了一个函数contains-token,因此最终解决了这个“正式”问题。它的目的是support classes

示例:

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

此函数可确保正确处理空格(不仅(U + 0020)),在类名重复的情况下有效,并且通常涵盖边缘情况。

注意:截至今日(2016-12-13),XPath 3.1的状态为候选推荐

答案 3 :(得分:3)

在XPath 2.0中,您可以:

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

如Christian Weiske所述: https://cweiske.de/tagebuch/XPath%3A%20Select%20element%20by%20class.htm

答案 4 :(得分:1)

HTML允许不区分大小写的元素和属性名称,然后class是一个以空格分隔的类名列表。我们在这里找到img代码和名为class的{​​{1}}:

date

请参阅:CSS Selector to XPath conversion

答案 5 :(得分:1)

在模板中注意减号!如果您在DOM中查询“my-ownclass”:

<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.