用xpathselect一个css类

我只想自己select一个叫做.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." "; } 

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

我们的问题

CSSselect器:

 .foo 

将select具有foo类的任何元素。

你如何在XPath中做到这一点?

尽pipeXPath比CSS强大,但XPath没有本地的CSS类select器 。 但是,有一个解决scheme。

正确的方式来做到这一点

XPath中的等效select器是:

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

函数规范化空间带前后空白(也可以用一个空格replace空白字符序列)。

(从更一般的意义上说)这也是CSSselect器的等价物:

 *[class~="foo"] 

它将匹配任何其class属性值为空白分隔值列表的元素,其中一个元素恰好等于foo

几个明显的,但错误的方法来做到这一点

XPathselect器:

 //*[@class="foo"] 

不起作用! 因为它不会匹配具有多个类的元素,例如

 <div class="foo bar"> 

如果类名周围有任何额外的空格,它也将不匹配:

 <div class=" foo "> 

“改进”的XPathselect器

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

也不行! 因为它与foob​​ar类错误地匹配元素

 <div class="foobar"> 

值得一提的是这个家伙,他是我在网上发现的这个问题的最早发布的解决scheme: http : //dubinko.info/blog/2007/10/01/simple-parsing-of-space-seprated-attributes-在-xpathxslt /

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

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

XPath 3.1引入了一个包含令牌的函数,从而最终解决了这个问题。 它旨在支持课程 。

例:

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

这个function确保了空白(不仅仅是 (U + 0020))正确处理,在class级名称重复的情况下工作,一般覆盖边缘情况。


注意:截至今天(2016-12-13)XPath 3.1已经具有候选推荐的状态。

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

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

另请参阅: CSSselect器到XPath的转换

注意模板中的减号标志! 如果您在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. 

在XPath 2.0中,您可以:

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

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