Возникли трудности с анализом грязного html-кода с помощью PHP DOMDocument


Я хочу иметь возможность загружать любой html-документ и редактировать его с помощью функций domdocument php.
Проблема в том, что некоторые веб-сайты, например facebook, добавляют пространства имен в стиле XML в свои теги.

<fb:like send="true" width="450" show_faces="true"></fb:like>

DOMDocument очень терпим к грязному коду, но он не принимает пространства имен в html-коде. Что происходит:

  • Если я использую loadHTML для загрузки кода, пространства имен будут удалены, но мне нужно, чтобы они остались
  • Если я использую loadXML для загрузки код, я получу тонны ошибок, в которых говорится, что я не загружаю допустимый XML

Итак, моя идея состояла в том, чтобы преобразовать html, который я получаю, в XML, чтобы я мог анализировать его с помощью loadXML. Мой вопрос в том, как мне это сделать, какой инструмент мне следует использовать (я слышал о Tidy, но не могу заставить его работать) или лучше использовать другой анализатор (анализатор, который может обрабатывать пространства имен в html-коде)

Фрагмент кода:

<?php
$html = file_get_contents($_POST['url']);

$domDoc = new DOMDocument();
$domDoc->loadHTML($html);

//Just do anything here. It doesn't matter what. For example I'm deleting the head tag
$headTag = $domDoc->getElementsByTagName("head")->item(0);
$headTagParent = $headTag->parentNode;
$headTagParent->removeChild($headTag);

echo $domDoc->saveHTML();

//This will work as expected for any url EXCEPT the ones that use XML namespaces like facebook does as described above. In case of such dirty coding the namespace will get deleted by DOMDocument

?>

Author: Syndace, 2015-05-07

1 answers

Нет простого способа проанализировать HTML с пространствами имен с помощью DOMDocument без потери пространств имен, но есть некоторые обходные пути:

  • Используйте другой синтаксический анализатор, который принимает пространства имен в коде HMTL. Посмотрите здесь для хорошего и подробного списка синтаксических анализаторов HTML. Это, вероятно, самый эффективный способ сделать это.
  • Если вы хотите придерживаться DOMDocument, вам в основном придется предварительно и после обработки кода.

    • Перед отправкой кода на DOMDocument->loadHTML, используйте регулярное выражение, циклы или что угодно, чтобы найти все теги пространства имен и добавить пользовательский атрибут к открывающим тегам, содержащим пространство имен.

      <fb:like send="true" width="450" show_faces="true"></fb:like>
      

      Затем приведет к

      <fb:like xmlNamespace="fb" send="true" width="450" show_faces="true"></fb:like>
      
    • Теперь передайте отредактированный код в DOMDocument->loadHTML. Он удалит пространства имен, но сохранит атрибуты, приводящие к

      <like xmlNamespace="fb" send="true" width="450" show_faces="true"></like>
      
    • Теперь (снова используя регулярное выражение, циклы или что угодно) найдите все теги с атрибутом xmlNamespace и замените атрибут фактическим пространством имен. Не забудьте также добавить пространство имен в закрывающие теги!

 2
Author: Syndace, 2017-05-23 12:33:03