【问题标题】:Selecting a css class with xpath使用 xpath 选择 css 类
【发布时间】: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." ";
}

【问题讨论】:

标签: php html xml xpath web


【解决方案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 的。
  • 这可能吗&lt;div class="foo\tbar"&gt;?我的意思是,用制表符分隔的类名。
  • 对于 $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 标签和名为 dateclass

    //*['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"]

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-26
        • 2012-05-28
        • 1970-01-01
        • 2011-02-06
        • 2012-02-08
        • 1970-01-01
        • 2012-02-18
        相关资源
        最近更新 更多