ChatGPT解决这个技术问题 Extra ChatGPT

使用 xpath 选择 css 类

我想自己选择一个名为 .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')
@Gordon 的回答很危险,如果类属性是“日期时间”,它也会匹配。 user716736 的回答更完整。

J
John Smith

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

我们的问题

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/


标准化空间需要什么?
“上面的答案”可能是指 MrGlass 的。
这可能<div class="foo\tbar">吗?我的意思是,用制表符分隔的类名。
但是
对于 $x('//div[contains(concat(" ", normalize-space(@class), " “), “健康)状况”)]')
@testerjoe2 你试过 //*[contains(concat(" ", normalize-space(@class), " "), " foo ")] 吗?
M
MrGlass

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

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


R
Robin Pokorny

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 等。
M
Memke

在 XPath 2.0 中,您可以:

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

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


不幸的是,截至 2017 年 6 月 12 日,这似乎并未由 chrome 实现。基于en.wikipedia.org/wiki/…,它似乎全面缺乏
h
hakre

HTML 允许不区分大小写的元素和属性名称,然后 class 是一个空格分隔的类名列表。我们在这里找到一个 img 标记和名为 dateclass

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

另请参阅:CSS Selector to XPath conversion


V
Vlado

当心模板中的减号!如果您在 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.