Я следую предложению этого вопроса. Надежный, зрелый HTML-парсер для PHP , о разборе html, который может быть искажен с помощью DOMDocument .
Есть ли простой способ перебрать анализируемый документ? Поэтому я хотел бы перебрать html таким образом.
$html='<ul> <li>value1</li> <li>value1</li> <li>value3 <p>subvalue</p> </li> </ul> <p>hello world</p>'; $doc = new DOMDocument(); $doc->loadHTML($html); ??? foreach (??? as $node) { print $node->nodeName.':'.$node->nodeValue; }
И получить результаты примерно так.
ul: li:value1 li:value2 li:value3 p:subvalue p:hello world
Использование $doc->childNodes
само по себе действительно не делает то, что я хочу. Так как это не похоже на нижние ветви дерева. Я использовал код, предложенный halfdan, и я получаю такие результаты.
html: html:value1 value1 value3 subvalue hello world
Попробуй это:
$doc = new DOMDocument(); $doc->loadHTML($html); showDOMNode($doc); function showDOMNode(DOMNode $domNode) { foreach ($domNode->childNodes as $node) { print $node->nodeName.':'.$node->nodeValue; if($node->hasChildNodes()) { showDOMNode($node); } } }
Вам нужно использовать PHP Simple HTML DOM Parser и следующий код:
<?php require_once 'simplehtmldom/simple_html_dom.php'; function iterateHtmlElements($html) { $dom = str_get_html($html); $dom->set_callback('handleElement'); $dom->__toString(); echo "\n"; } function handleElement(simple_html_dom_node $elem) { if($elem->tag == 'text') { echo $elem->innertext(); } else { echo "\n" . $elem->tag . ": "; } } $html='<ul> <li>value1</li> <li>value1</li> <li>value3 <p>subvalue</p> </li> </ul> <p>hello world</p>'; iterateHtmlElements($html);
Он работает точно так, как ожидалось. Я проверил его с предоставленным вами вводом и получил следующие результаты:
> php test2.php ul: li: value1 li: value1 li: value3 p: subvalue p: hello world
У меня возникли проблемы с элементами, имеющими c-данные, где даже элементы, у которых не было детей, возвращающих их.
Я не знаю, почему это было.
Работа, которую я нашел, заключалась в том, чтобы изменить
if($node->hasChildNodes()) { showDOMNode($node); }
в
if($node->childNodes->length != 1) { showDOMNode($node); }
И теперь код работает отлично.
Один из способов – следовать дереву следующим образом:
function next_node($node) { if($node->firstChild != null) { return $node->firstChild; } if($node->nextSibling != null) { return $node->nextSibling; } for($node = $node->parentNode; $node != null; $node = $node->parentNode) { if($node->nextSibling != null) { return $node->nextSibling; } } return null; } for($node = $doc; $node != null; $node = next_node($node)) { // handle node (read-only mode, if you need read-write // you have to save all the nodes in an array and then // use that array // ... }
Это работает для большинства документов, однако это выглядит так, как будто parentNode
как-то неправильно настроен, а next_node()
возвращает неверную информацию.