通过classname获取DOM元素

我正在使用PHP的DOM ,我试图得到一个DOM节点中有一个给定的类名称的元素。 得到这个子元素的最好方法是什么?

更新:我结束了使用PHP的Mechanize ,这是更容易处理。

更新: *[@class~='my-class'] class〜 *[@class~='my-class'] cssselect器的Xpath版本

所以在我的评论下面回应hakre的评论我很好奇,看着Zend_Dom_Query背后的代码。 它看起来像上面的select器被编译为以下xpath(未经testing):

[contains(concat(' ', normalize-space(@class), ' '), ' my-class ')]

所以PHP将是:

 $dom = new DomDocument(); $dom->load($filePath); $finder = new DomXPath($dom); $classname="my-class"; $nodes = $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]"); 

基本上我们在这里所做的就是对class属性进行规范化,这样即使是一个类也是以空格为界的,而完整的类列表是以空格为界的。 然后追加我们正在寻找一个空间类。 这样,我们正在有效地寻找和findmy-class实例。


使用xpathselect器?

 $dom = new DomDocument(); $dom->load($filePath); $finder = new DomXPath($dom); $classname="my-class"; $nodes = $finder->query("//*[contains(@class, '$classname')]"); 

如果它只有一种types的元素,您可以用特定的标记名replace*

如果你需要做很多非常复杂的select,我会推荐Zend_Dom_Query它支持CSSselect器语法(la jQuery):

 $finder = new Zend_Dom_Query($html); $classname = 'my-class'; $nodes = $finder->query("*[class~=\"$classname\"]"); 

如果你想在没有zend的情况下获得这个类的innerhtml,你可以使用这个:

 $dom = new DomDocument(); $dom->load($filePath); $classname = 'main-article'; $finder = new DomXPath($dom); $nodes = $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]"); $tmp_dom = new DOMDocument(); foreach ($nodes as $node) { $tmp_dom->appendChild($tmp_dom->importNode($node,true)); } $innerHTML.=trim($tmp_dom->saveHTML()); echo $innerHTML; 

我认为接受的方式更好,但我想这也可以

 function getElementByClass(&$parentNode, $tagName, $className, $offset = 0) { $response = false; $childNodeList = $parentNode->getElementsByTagName($tagName); $tagCount = 0; for ($i = 0; $i < $childNodeList->length; $i++) { $temp = $childNodeList->item($i); if (stripos($temp->getAttribute('class'), $className) !== false) { if ($tagCount == $offset) { $response = $temp; break; } $tagCount++; } } return $response; } 

还有一种不使用DomXPathZend_Dom_Query

基于dav的原始函数,我写了下面的函数,返回父节点的标签和类匹配参数的所有子节点。

 function getElementsByClass(&$parentNode, $tagName, $className) { $nodes=array(); $childNodeList = $parentNode->getElementsByTagName($tagName); for ($i = 0; $i < $childNodeList->length; $i++) { $temp = $childNodeList->item($i); if (stripos($temp->getAttribute('class'), $className) !== false) { $nodes[]=$temp; } } return $nodes; } 

假设你有一个variables$html下面的HTML:

 <html> <body> <div id="content_node"> <p class="a">I am in the content node.</p> <p class="a">I am in the content node.</p> <p class="a">I am in the content node.</p> </div> <div id="footer_node"> <p class="a">I am in the footer node.</p> </div> </body> </html> 

使用getElementsByClass就像下面这样简单:

 $dom = new DOMDocument('1.0', 'utf-8'); $dom->loadHTML($html); $content_node=$dom->getElementById("content_node"); $div_a_class_nodes=getElementsByClass($content_node, 'div', 'a');//will contain the three nodes under "content_node". 

DOMDocumentinput缓慢, phpQuery有内存泄漏问题。 我结束了使用:

https://github.com/wasinger/htmlpagedom

要select一个class级:

 include 'includes/simple_html_dom.php'; $doc = str_get_html($html); $href = $doc->find('.lastPage')[0]->href; 

我希望这可以帮助别人