Цикл над DOMDocument

Я следую предложению этого вопроса. Надежный, зрелый 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 

Solutions Collecting From Web of "Цикл над DOMDocument"

Попробуй это:

 $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() возвращает неверную информацию.