Web

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

Я использую 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

Как правильно выбрать имя домена для своего сайта? Лучшие примеры

Web

Пример использования bind_result/get_result

Web

Использование цикла для SimpleXML с помощью foreach в php

Клиент-серверная архитектура: что это такое и для чего ее используют?
Web

Клиент-серверная архитектура: что это такое и для чего ее используют?