Получение элементов DOM по имени класса
Я использую PHP DOM и я пытаюсь получить элемент в узле DOM, который имеет заданное имя класса. Каков наилучший способ получить этот подэлемент?
обновление: Я в конечном итоге с помощью Mechanize
для PHP, с которым было намного проще работать.
5 ответов:
обновление: Xpath версия
*[@class~='my-class']
селектор cssпоэтому после моего комментария ниже в ответ на комментарий Хакра, мне стало любопытно и заглянул в код за
Zend_Dom_Query
. Похоже, что приведенный выше селектор компилируется в следующий xpath (непроверенный):
[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
атрибут так, что даже один класс ограничен пробелами, и полный список классов ограничен пробелами. Затем добавьте класс, который мы ищем, с пробелом. Таким образом, мы эффективно ищем и находим только экземплярыmy-class
.
использовать селектор xpath?
$dom = new DomDocument(); $dom->load($filePath); $finder = new DomXPath($dom); $classname="my-class"; $nodes = $finder->query("//*[contains(@class, '$classname')]");
если это только один тип элемента, который вы можете заменить
*
с конкретным tagname.Если вам нужно сделать много этого с очень сложным селектором, я бы рекомендовал
Zend_Dom_Query
, который поддерживает Синтаксис селектора CSS (a la jQuery):$finder = new Zend_Dom_Query($html); $classname = 'my-class'; $nodes = $finder->query("*[class~=\"$classname\"]");
Если вы хотите получить innerhtml класса без zend вы можете использовать это:
$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; }
есть и другой подход без использования
DomXPath
илиZend_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; }
предположим, у вас есть переменная
$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".
DOMDocument медленно набирает и phpQuery имеет проблемы с утечкой памяти. Я в конечном итоге с помощью:
https://github.com/wasinger/htmlpagedom
выбрать класс:
include 'includes/simple_html_dom.php'; $doc = str_get_html($html); $href = $doc->find('.lastPage')[0]->href;
Я надеюсь, что это поможет кому-то еще, а также