Вопрос

У меня есть несколько устаревших документов, похожих на HTML.То есть они выглядят как HTML, но имеют дополнительные теги, не являющиеся частью HTML.

<strong>This is an example of a <pseud-template>fake tag</pseud-template></strong>

Мне нужно проанализировать эти файлы.PHP — единственный доступный инструмент.Документы даже близко не похожи на правильно сформированный XML.

Моя первоначальная мысль заключалась в том, чтобы использовать методы loadHTML в DOMDocument PHP.Однако эти методы ограничивают составные HTML-теги и отказываются анализировать строку/файл.

$oDom = new DomDocument();
$oDom->loadHTML("<strong>This is an example of a <pseud-template>fake tag</pseud-template></strong>");
//gives us
DOMDocument::loadHTML() [function.loadHTML]: Tag pseud-template invalid in Entity, line: 1 occured in ....

Единственное решение, которое мне удалось придумать, — это предварительная обработка файлов с помощью функций замены строк, которые удалят недопустимые теги и заменят их действительным тегом HTML (возможно, диапазоном с идентификатором имени тега).

Есть ли более элегантное решение?Способ сообщить DOMDocument о дополнительных тегах, которые следует считать действительными?Существует ли другой, надежный класс/объект синтаксического анализа HTML для PHP?

(если это не очевидно, я не считаю регулярные выражения допустимым решением)

Обновлять:Информация в поддельных тегах является частью цели, поэтому что-то вроде Tidy не вариант.Кроме того, мне нужно что-то, что выполняет для меня некоторый уровень, если не всю, очистки правильности формата, поэтому я в первую очередь искал метод loadHTML DomDocument.

Это было полезно?

Решение

Вы можете подавить предупреждения с помощью libxml_use_internal_errors, при загрузке документа.Например.:

libxml_use_internal_errors(true);
$doc = new DomDocument();
$doc->loadHTML("<strong>This is an example of a <pseud-template>fake tag</pseud-template></strong>");
libxml_use_internal_errors(false);

Если по какой-то причине вам нужен доступ к предупреждениям, используйте libxml_get_errors

Другие советы

Интересно, передается ли «плохой» HTML через HTML аккуратный может помочь в качестве первого прохода?Возможно, стоит посмотреть: если вам удастся добиться правильного формата документа, возможно, вы сможете загрузить его как обычный XML-файл с помощью DomDocument.

@Twan Вам не нужен DTD для Domdocument, чтобы разобраться с пользовательским XML.Просто используйте DOMDocument->load(), и пока XML имеет правильный формат, он может его прочитать.

Как только вы добьетесь, что файлы будут правильно сформированы, вы сможете начать изучать анализаторы XML, прежде чем вы станете S.O.L.Лок Алехо сказал, что ты можешь посмотреть HTML-ТИДИ, но похоже, что это специфично для HTML, и я не знаю, как это будет выглядеть с вашими пользовательскими элементами.

Я не считаю регулярные выражения здесь допустимым решением.

Пока вы не приобрели правильную форму, это может быть вашим единственным вариантом.Как только вы доведете документы до этого этапа, с функциями DOM все будет в порядке.

Взгляните на парсер в порту PHP Fit.Код чист и изначально был разработан для загрузки грязного HTML, сохраненного в Word.Он настроен на извлечение таблиц, но его можно легко адаптировать.

Вы можете увидеть источник здесь:http://gerd.exit0.net/pat/PHPFIT/PHPFIT-0.1.0/Parser.phps

Модульный тест покажет вам, как его использовать:http://gerd.exit0.net/pat/PHPFIT/PHPFIT-0.1.0/test/parser.phps

Мое быстрое и грязное решение этой проблемы заключалось в запуске цикла, который сопоставляет мой список пользовательских тегов с регулярным выражением.Регулярное выражение не улавливает теги, внутри которых есть другой внутренний пользовательский тег.

При обнаружении совпадения вызывается функция для обработки этого тега и возвращает «обработанный HTML».Если этот пользовательский тег находился внутри другого пользовательского тега, то родительский тег становится бездетным из-за того, что вместо дочернего элемента был вставлен фактический HTML-код, который будет сопоставлен с регулярным выражением и обработан на следующей итерации цикла.

Цикл завершается, когда не осталось сопоставляемых бездетных пользовательских тегов.В целом это итеративный (цикл while), а не рекурсивный.

@Алан Шторм

Ваш комментарий к моему другому ответу заставил меня задуматься:

Когда вы загружаете HTML-файл с помощью DOMDocument, он, похоже, выполняет некоторый уровень очистки:хорошо сформирован, НО требует, чтобы все ваши теги были законными HTML-тегами.Я ищу что-то, что делает первое, но не последнее.(Алан Шторм)

Запустите регулярное выражение (извините!) по тегам, и когда оно найдет недопустимый элемент HTML, замените его допустимым элементом, который, как вы знаете, не существует ни в одном из документов (blink приходит на ум...), и присвойте ему значение атрибута с именем недопустимого элемента, чтобы потом можно было переключить его обратно.например:

$code = str_replace("<pseudo-tag>", "<blink rel=\"pseudo-tag\">", $code);
// and then back again...
$code = preg_replace('<blink rel="(.*?)">', '<\1>', $code);

очевидно, что этот код не будет работать, но общую идею вы уловили?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top