Есть много способов обработки HTML / XML DOM, большинство из которых уже были упомянуты. Поэтому я не буду пытаться перечислить их сам.
Я просто хочу добавить, что лично я предпочитаю использовать расширение DOM и почему:
- iit оптимально использует преимущество в производительности базового кода C
- это OO PHP (и позволяет мне его подкласс)
- это довольно низкий уровень (что позволяет мне использовать его как не раздутый фундамент для более продвинутого поведения)
- обеспечивает доступ ко всем частям DOM (в отличие, например, от SimpleXml, который игнорирует некоторые из менее известных функций XML)
- имеет синтаксис, используемый для сканирования DOM, аналогичный синтаксису, используемому в нативном Javascript.
И хотя мне не хватает возможности использовать селекторы CSS для DOMDocument
, есть довольно простой и удобный способ добавить эту функцию: создание подклассов DOMDocument
и добавление JS-подобных querySelectorAll
и querySelector
методов к Ваш подкласс.
Для анализа селекторов я рекомендую использовать очень минималистичный компонент CssSelector из Symfony framework . Этот компонент просто переводит селекторы CSS в селекторы XPath, которые затем могут быть переданы в DOMXpath
для получения соответствующего Nodelist.
Затем вы можете использовать этот (все еще очень низкоуровневый) подкласс в качестве основы для более высокоуровневых классов, например, для. анализировать очень специфические типы XML или добавлять более jQuery-подобное поведение.
Приведенный ниже код идет прямо из моей библиотеки DOM-Query и использует описанную мной технику.
Для разбора HTML:
namespace PowerTools;
use \Symfony\Component\CssSelector\CssSelector as CssSelector;
class DOM_Document extends \DOMDocument {
public function __construct($data = false, $doctype = 'html', $encoding = 'UTF-8', $version = '1.0') {
parent::__construct($version, $encoding);
if ($doctype && $doctype === 'html') {
@$this->loadHTML($data);
} else {
@$this->loadXML($data);
}
}
public function querySelectorAll($selector, $contextnode = null) {
if (isset($this->doctype->name) && $this->doctype->name == 'html') {
CssSelector::enableHtmlExtension();
} else {
CssSelector::disableHtmlExtension();
}
$xpath = new \DOMXpath($this);
return $xpath->query(CssSelector::toXPath($selector, 'descendant::'), $contextnode);
}
[...]
public function loadHTMLFile($filename, $options = 0) {
$this->loadHTML(file_get_contents($filename), $options);
}
public function loadHTML($source, $options = 0) {
if ($source && $source != '') {
$data = trim($source);
$html5 = new HTML5(array('targetDocument' => $this, 'disableHtmlNsInDom' => true));
$data_start = mb_substr($data, 0, 10);
if (strpos($data_start, '<!DOCTYPE ') === 0 || strpos($data_start, '<html>') === 0) {
$html5->loadHTML($data);
} else {
@$this->loadHTML('<!DOCTYPE html><html><head><meta charset="' . $encoding . '" /></head><body></body></html>');
$t = $html5->loadHTMLFragment($data);
$docbody = $this->getElementsByTagName('body')->item(0);
while ($t->hasChildNodes()) {
$docbody->appendChild($t->firstChild);
}
}
}
}
[...]
}
См. Также Разбор XML-документов с помощью селекторов CSS , создатель Symfony Фабьен Потенциер (Fabien Potencier) о своем решении создать компонент CssSelector для Symfony и способы его использования.