Intereting Posts
Связывать пользовательские данные с датой в bootstrap datepicker случайный многомерный массив php и получить исходный индекс массива Как я могу использовать php для удаления тегов с пустым текстовым узлом? Пользовательский заказ Mysql по алфавиту и по алфавиту: Вызов неопределенного метода Illuminate \ Database \ Query \ Builder :: notify () Как я могу группировать элементы формы Перенаправление приложений iFrame для Facebook PHP 5.2 Примечание: использование неопределенной константы __DIR__ – предполагается '__DIR__ PHP GD изменение размера прозрачного изображения, дающего черную границу вставить массив в строку, разделенную запятыми, из запроса mysql Список изображений (01.png) и описания (01.txt) из каталога Путаница PHP-типа Codeigniter – Записывать несколько направляющих в один файл с новой структурой каталогов Безопасный способ отправки почты через PHP многим пользователям Symfony 2 – Как удалить пакет?

Получение элементов DOM по имени класса

Я использую PHP DOM, и я пытаюсь получить элемент в узле DOM с заданным именем класса. Каков наилучший способ получить этот подэлемент?

Обновление: я закончил использование Mechanize для PHP, с которым было намного легче работать.

Обновление: версия Xpath *[@class~='my-class'] css-селектор

Поэтому после моего комментария ниже в ответ на комментарий Хакре мне стало любопытно и посмотрел код Zend_Dom_Query . Похоже, что вышеупомянутый селектор скомпилирован в следующий xpath (untested):

[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')]"); 

Если это только один тип элемента, вы можете заменить * на конкретный тэг.

Если вам нужно сделать это много с помощью очень сложного селектора, я бы порекомендовал 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; 

Надеюсь, это поможет и кому-то еще