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

Как я могу обновить код, в котором используется устаревшая функция each()

Как и на чём лучше писать сайты?
Web

Как и на чём лучше писать сайты?

Web

Как делать асинхронные HTTP-запросы в PHP

Web

Защита веб-серверов PHP

×