Я использую PHP DOM и пытаюсь получить элемент в узле DOM, который имеет заданное имя класса. Какой лучший способ получить этот подэлемент?
Ответ 1
Итак, 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-селекторов (то есть jQuery):
$finder = new Zend_Dom_Query($html);
$classname = 'my-class';
$nodes = $finder->query("*[class~=\"$classname\"]");
Ответ 2
Если вы хотите получить 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;
Ответ 3
Я думаю, что принятый способ лучше, но мне кажется, что это тоже может сработать:
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;
}
Ответ 4
Существует также другой подход, не требующий использования 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">Я нахожусь в узле содержимого.</p>
<p class="a">Я нахожусь в узле содержимого.</p>
<p class="a">Я нахожусь в узле содержимого.</p>
</div>
<div id="footer_node">
<p class="a">Я нахожусь в узле нижнего колонтитула.</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');//будет содержать три узла под "content_node".
Ответ 5
Нативная обработка DOM в PHP настолько абсурдно плоха, что сделайте себе одолжение и используйте этот или любой другой современный пакет для разбора HTML, который может справиться с этим в несколько строк, — установите paquettg/php-html-parser с помощью:
composer require paquettg/php-html-parser
Затем создайте файл .php в той же папке с таким содержанием:
<?php
// загружаем зависимости через Composer
require __DIR__ . '/vendor/autoload.php';
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadFromUrl("https://example.com");
$links = $dom->find('.classname a');
foreach ($links as $link) {
echo $link->getAttribute('href');
}
Информацию о том, как установить Composer, вы найдете на домашней странице Composer.
Web