使用 xpath 选择 css 类
Posted
技术标签:
【中文标题】使用 xpath 选择 css 类【英文标题】:Selecting a css class with xpath 【发布时间】:2012-02-07 04:45:05 【问题描述】:我只想选择一个名为 .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." ";
【问题讨论】:
那段 html 呢? (更喜欢向我们展示 asXML() 的 simpleXml 输出,因为它更接近 xpath) 如果有多个类你需要做contains(@class, 'date')
php - Parse All Links That Contain A Speciffic Word In "href" Tag的可能重复
XPath: How to match attributes that contain a certain string的可能重复
@Gordon 的回答很危险,如果类属性是“datetime”,它也会匹配。 user716736的回答比较完整。
【参考方案1】:
我想写这个问题的规范答案,因为上面的答案有问题。
我们的问题
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/
【讨论】:
规范化空间需要什么? “上面的答案”可能是指 MrGlass 的。 这可能吗<div class="foo\tbar">
?我的意思是,用制表符分隔的类名。
但 和 对于 $x('//div[contains(concat(" ", normalize -space(@class), " "), "条件")]')
@testerjoe2 你试过//*[contains(concat(" ", normalize-space(@class), " "), " foo ")]
吗?【参考方案2】:
XPath 3.1 引入了一个函数contains-token,因此最终“正式”解决了这个问题。专为support classes设计。
示例:
//*[contains-token(@class, "foo")]
此函数确保正确处理空白(不仅是 (U+0020)),在类名重复的情况下工作,并且通常涵盖边缘情况。
注意:截至今天 (2016-12-13) XPath 3.1 的状态为候选推荐。
【讨论】:
它在今天最新的 chrome 中不起作用。在它起作用之前,我们如何绕过 //*[contains(@class, "foo")] 也会选择任何包含 foo 的类的限制,例如 foobar、fooz 等。【参考方案3】:在 XPath 2.0 中,您可以:
//*[count(index-of(tokenize(@class, '\s+' ), 'foo')) = 1]
正如克里斯蒂安·韦斯克所说: https://cweiske.de/tagebuch/XPath%3A%20Select%20element%20by%20class.htm
【讨论】:
不幸的是,截至 2017 年 6 月 12 日,chrome 似乎并未实现此功能。基于en.wikipedia.org/wiki/…,它似乎全面缺乏【参考方案4】:当心模板中的减号!如果您在 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.
【讨论】:
【参考方案5】:HTML 允许不区分大小写的元素和属性名称,然后 class 是一个空格分隔的类名列表。在这里,我们使用 img
标签和名为 date
的 class
:
//*['IMG' = translate(name(.), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')]/@*['CLASS' = translate(name(.), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') and contains(concat(' ', normalize-space(.), ' '), concat(' ', 'date', ' '))]
另请参阅:CSS Selector to XPath conversion
【讨论】:
【参考方案6】://[@class="date"]
不是有效的 xpath。
试试//*[@class="date"]
,或者如果你知道这是一张图片,//img[@class="date"]
【讨论】:
以上是关于使用 xpath 选择 css 类的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Chrome 开发者工具中使用 XPath 或 CSS 选择器搜索 DOM 元素?