Simplexml: синтаксический анализ HTML оставляет вложенные элементы внутри элемента с текстовым узлом

Я пытаюсь разобрать конкретный html-документ, какой-то словарь, содержащий около 10000 слов и описание. Это прошло хорошо, пока я не заметил, что записи в определенном формате не получают синтаксический анализ.

Вот пример:

<?php $html = ' <p> <b> <span>zot; zotz </span> </b> <span>Nista; nula. Isto <b>zilch; zip.</b> </span> </p> '; $xml = simplexml_load_string($html); var_dump($xml); ?> 

Результатом var_dump () является:

  object(SimpleXMLElement)#1 (2) { ["b"]=> object(SimpleXMLElement)#2 (1) { ["span"]=> string(10) "zot; zotz " } ["span"]=> string(39) "Nista; nula. Isto " } 

Как вы можете видеть – Simplexml сохранил текстовый узел внутри тега, но оставил дочерний узел и текст внутри.

Я также пробовал:

  $doc = new DOMDocument(); $doc->loadHTML($html); $xml = simplexml_import_dom($doc); 

с тем же результатом.

Поскольку мне казалось, что это обычная проблема при анализе html, я попытался разобраться с этим, но только место, которое признает эту проблему в этом блоге: https://hakre.wordpress.com/2013/07/09/simplexml-and- json-encode-in-php-part-i /, но не предлагает никакого решения.

Есть только слишком обобщенные сообщения и ответы о разборе HTML в SO.

Есть ли простой способ справиться с этим? Или я должен изменить свою стратегию?

Ваше замечание верно: SimpleXML предлагает только дочерний элемент-узел, а не дочерние текстовые узлы. Решение состоит в том, чтобы переключиться на DOMDocument, поскольку он может обращаться ко всем узлам, текстовым и дочерним элементам.

 // first span element $span = dom_import_simplexml($xml->span); foreach ($span->childNodes as $child) { printf(" - %s : %s\n", get_class($child), $child->nodeValue ); } 

В этом примере показано, что dom_import_simplexml используется для более конкретного элемента элемента <span> и обход выполняется над дочерними элементами соответствующего объекта DOMElement .

Выход:

  - DOMText : Nista; nula. Isto - DOMElement : zilch; zip. - DOMText : -  - DOMText : Nista; nula. Isto - DOMElement : zilch; zip. - DOMText : 

Первая запись – это первый текстовый узел в элементе <span> . За ним следует элемент <b> (который снова содержит некоторый текст), а затем из другого текстового узла, который состоит только из пробелов.

Функция dom_import_simplexml особенно полезна, когда SimpleXMLElement слишком прост для более дифференцированного доступа к данным в XML-документе. Как и в случае с вами.

Пример полностью:

 $html = <<<HTML <p> <b> <span>zot; zotz </span> </b> <span>Nista; nula. Isto <b>zilch; zip.</b> </span> </p> HTML; $xml = simplexml_load_string($html); // first span element $span = dom_import_simplexml($xml->span); foreach ($span->childNodes as $child) { printf(" - %s : %s\n", get_class($child), $child->nodeValue ); } - $html = <<<HTML <p> <b> <span>zot; zotz </span> </b> <span>Nista; nula. Isto <b>zilch; zip.</b> </span> </p> HTML; $xml = simplexml_load_string($html); // first span element $span = dom_import_simplexml($xml->span); foreach ($span->childNodes as $child) { printf(" - %s : %s\n", get_class($child), $child->nodeValue ); }