jQuery-подобные селекторы для PHP DOMDocument - PullRequest
15 голосов
/ 14 июля 2009

Я работаю с DOMDocument, и мне интересно, существует ли какой-либо способ использования CSS-подобных селекторов для выбора узлов, как это было бы в jQuery .

Пример ситуации: я анализирую файл XML, один фрагмент которого выглядит следующим образом:

<gesmes:Envelope>
    <gesmes:subject>Reference rates</gesmes:subject>
    <gesmes:Sender>
        <gesmes:name>European Central Bank</gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time="2009-07-13">
            <Cube currency="USD" rate="1.3975"/>
            <Cube currency="JPY" rate="129.03"/>
            <Cube currency="BGN" rate="1.9558"/>
            <Cube currency="CZK" rate="26.028"/>
        </Cube>
    </Cube>
</gesmes:Envelope>

Доступ к этой структуре с помощью jQuery-подобных селекторов был бы очень простым. Например, я мог бы использовать

$("Cube[currency]")

для извлечения всех элементов Cube с атрибутом currency.

Но как я могу сделать то же самое с PHP DOMDocument? Я хотел бы выбрать элементы, которые имеют атрибут или имеют конкретное значение атрибута.

Ответы [ 5 ]

20 голосов
/ 14 июля 2009

Если вы хотите управлять DOM ala Jquery, PHPQuery - это то, что вам нужно.

http://code.google.com/p/phpquery/

Простой пример того, что вы можете сделать с ним.

// almost everything can be a chain
$li = null;
$doc['ul > li']
        ->addClass('my-new-class')
        ->filter(':last')
                ->addClass('last-li');
14 голосов
/ 14 июля 2009

Взгляните на класс DOMXPath в PHP. Он использует XPath, поэтому вам нужно ознакомиться с синтаксисом XPath, если вы не знакомы с ним. Есть некоторая документация по MSDN или W3Schools , или вы можете прочитать спецификацию W3 , если вы особенно смелы.

Чтобы решить примерную проблему: //cube[@currency] - это запрос XPath, который выбирает все элементы в документе с атрибутом валюты. Использование этого с классом DOMXPath будет выглядеть так:

$xpath = new DOMXpath($myDomDocument);
$cubesWithCurrencies = $xpath->query('//cube[@currency]');

$cubesWithCurrencies теперь DOMNodeList, который вы можете повторять.

6 голосов
/ 09 июля 2015

Я создал библиотеку, которая позволяет сканировать документы HTML5 и XML точно так же, как вы делаете это с jQuery.

Вы можете найти библиотеку на GitHub .

Это должно позволить вам делать именно то, что вы хотите!

Под капотом используется symfony / DomCrawler для преобразования селекторов CSS в селекторы XPath. Он всегда использует один и тот же DomDocument, даже при передаче одного объекта другому, чтобы обеспечить достойную производительность.

Библиотека также включает собственный автозагрузчик нулевой конфигурации для PSR-0-совместимых библиотек. Приведенный пример должен работать из коробки без какой-либо дополнительной настройки.


Пример использования:

namespace PowerTools;

// Get file content
$htmlcode = file_get_contents( 'https://github.com' );

// Define your DOMCrawler based on file string
$H = new DOM_Query( $htmlcode );

// Define your DOMCrawler based on an existing DOM_Query instance
$H = new DOM_Query( $H->select('body') );

// Passing a string (CSS selector)
$s = $H->select( 'div.foo' );

// Passing an element object (DOM Element)
$s = $H->select( $documentBody );

// Passing a DOM Query object
$s = $H->select( $H->select('p + p') );

// Select the body tag
$body = $H->select('body');

// Combine different classes as one selector to get all site blocks
$siteblocks = $body->select('.site-header, .masthead, .site-body, .site-footer');

// Nest your methods just like you would with jQuery
$siteblocks->select('button')->add('span')->addClass('icon icon-printer');

// Use a lambda function to set the text of all site blocks
$siteblocks->text(function( $i, $val) {
    return $i . " - " . $val->attr('class');
});

// Append the following HTML to all site blocks
$siteblocks->append('<div class="site-center"></div>');

// Use a descendant selector to select the site's footer
$sitefooter = $body->select('.site-footer > .site-center');

// Set some attributes for the site's footer
$sitefooter->attr(array('id' => 'aweeesome', 'data-val' => 'see'));

// Use a lambda function to set the attributes of all site blocks
$siteblocks->attr('data-val', function( $i, $val) {
    return $i . " - " . $val->attr('class') . " - photo by Kelly Clark";
});

// Select the parent of the site's footer
$sitefooterparent = $sitefooter->parent();

// Remove the class of all i-tags within the site's footer's parent
$sitefooterparent->select('i')->removeAttr('class');

// Wrap the site's footer within two nex selectors
$sitefooter->wrap('<section><div class="footer-wrapper"></div></section>');

[...]

Поддерживаемые методы:
  1. Переименовано в 'select' по понятным причинам
  2. Переименовано в 'void', поскольку слово 'empty' в PHP зарезервировано
1 голос
/ 17 января 2014

Вы можете использовать компонент Symfony DomCrawler, позволяющий использовать селекторы css для обхода DOM: https://packagist.org/packages/symfony/dom-crawler

0 голосов
/ 14 июля 2009
...