JQuery-подобный селектор для PHP DOMDocument
Я работаю с 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
? Я хотел бы выбрать элементы, которые имеют атрибут, или имеют определенное значение атрибута.
Ответы
Ответ 1
Если вы хотите манипулировать 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');
Ответ 2
Взгляните на класс DOMXPath
в PHP. Он использует XPath, поэтому вам нужно будет прочитать синтаксис XPath, если вы не знакомы с ним. Там есть документация по MSDN или W3Schools, или вы можете прочитать спецификацию W3, если вы особенно смелы.
Чтобы решить вашу проблему с примером: //cube[@currency]
- это запрос XPath, который выбирает все элементы в документе с атрибутом валюты. Использование этого класса DOMXPath
будет выглядеть так:
$xpath = new DOMXpath($myDomDocument);
$cubesWithCurrencies = $xpath->query('//cube[@currency]');
$cubesWithCurrencies
теперь DOMNodeList
, который вы можете перебрать.
Ответ 3
Я создал библиотеку, которая позволяет обходить 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 footer
$sitefooter = $body->select('.site-footer > .site-center');
// Set some attributes for the site 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 footer
$sitefooterparent = $sitefooter->parent();
// Remove the class of all i-tags within the site footer parent
$sitefooterparent->select('i')->removeAttr('class');
// Wrap the site footer within two nex selectors
$sitefooter->wrap('<section><div class="footer-wrapper"></div></section>');
[...]
Поддерживаемые методы:
- Переименовано 'select', по понятным причинам
- Переименовано 'void', так как 'empty' является зарезервированным словом в PHP
Ответ 4
Вы можете использовать компонент Symfony DomCrawler, позволяющий использовать селектора css для перемещения DOM:
https://packagist.org/packages/symfony/dom-crawler
Ответ 5
XPath - это именно то, что вы ищете, вот довольно хороший список возможных селекторов