Как разобрать недопустимый (плохой / не правильно сформированный) XML?
В настоящее время я работаю над функцией, которая включает в себя синтаксический анализ XML, который мы получаем из другого продукта. Я решил провести несколько тестов с некоторыми реальными данными клиента, и похоже, что другой продукт допускает ввод данных от пользователей, который следует считать недопустимым. В любом случае, мне все еще нужно попытаться найти способ его анализа. Мы используем javax.xml.parsers.DocumentBuilder и я получаю ошибку при вводе, которая выглядит следующим образом.
Как вы можете видеть, в описании есть то, что кажется недопустимым тегом внутри (<THIS-IS-PART-OF-DESCRIPTION>). Известно, что этот тег описания является конечным тегом и внутри него не должно быть вложенных тегов. Несмотря на это, это все еще проблема и приводит к исключению при DocumentBuilder.parse(...)
Я знаю, что это недопустимый XML, но он предсказуемо недействителен. Есть идеи о способе анализа такого ввода?
Неформальная оценка предсказуемости нарушений не помогает. Эти текстовые данные не являются XML. Никакие соответствующие инструменты или библиотеки XML не могут помочь вам обработать их.
Варианты, наиболее желательные в первую очередь:
Попросите провайдера исправить проблему со своей стороны. Требуйте правильно сформированный XML. (Технически фраза правильно сформированный XML избыточна, но может быть полезна для выделения.)
Используйте толерантный анализатор разметки для устранения проблемы перед синтаксическим анализом в формате XML:
Прекрасный супPython: основан на Python. Смотрите Примечания в разделе "Различия между анализаторами". Смотрите также ответы на этот вопрос, чтобы узнать больше предложений по работе с неправильно сформированной разметкой в Python, включая, в частности, recover=True lxml. Смотрите также Этот ответ о том, как использовать codecs.EncodedFile() для очистки от недопустимых символов.
Обработайте данные в виде текста вручную с помощью текстового редактора или программно, используя символьные / строковые функции. Выполнение этого программно может варьироваться от сложного до невозможного, поскольку то, что кажется предсказуемым, часто таковым не является - нарушение правил редко ограничено правилами.
Для ошибок с недопустимыми символами используйте регулярное выражение для удаления / замены недопустимых символов:
Для амперсандов используйте регулярное выражение для замены совпадений на &: credit: blhsin, demo
&(?!(?:#\d+|#x[0-9a-f]+|\w+);)
Обратите внимание, что приведенные выше регулярные выражения не учитывают комментарии или CDATA разделы.
Ответ 2
Стандартный анализатор XML НИКОГДА не примет недопустимый XML по своей конструкции.
Ваш единственный вариант - предварительно обработать входные данные, чтобы удалить "предсказуемо недопустимое" содержимое, или обернуть его в CDATA, перед его разбором.
Ответ 3
Принятый ответ является хорошим советом и содержит очень полезные ссылки.
Я хотел бы добавить, что этот и многиедругие случаи неправильно сформированного и / или DTD-недопустимого XML могут быть исправлены с помощью SGML, стандартизированного ISO надмножества HTML и XML. В вашем случае работает объявление фиктивного THIS-IS-PART-OF-DESCRIPTION элемента как SGML empty element, а затем использование, например. osx программа (часть пакета OpenSP / OpenJade SGML) для преобразования его в XML. Например, если вы предоставите следующее в osx
он выведет правильно сформированный XML для дальнейшей обработки с помощью инструментов XML по вашему выбору.
Обратите внимание, однако, что в вашем примере фрагмента есть другая проблема, заключающаяся в том, что имена элементов, начинающиеся с букв xml или XML или Xml и т.д., зарезервированы в XML и не будут приняты соответствующими анализаторами XML.
Ниже приведен не совсем ответ для данного конкретного случая, но я нашел это в Интернете (благодаря inuyasha82 на Coderwall). Этот фрагмент кода вдохновил меня на решение другой подобной проблемы при работе с неверно сформированными XML-файлами, поэтому я делюсь им здесь.
Пожалуйста, не редактируйте то, что ниже, так как оно есть на оригинальном веб-сайте.
Формат XML требует, чтобы был допустимым уникальный корневой элемент, объявленный в документе. Так, например, допустимый xml - это:
Это будет считаться неправильно сформированным XML, поэтому многие анализаторы xml просто выдают исключение с жалобой на отсутствие корневого элемента. И т.д.
В этом примере есть решение о том, как решить эту проблему и успешно разобрать искаженный xml, приведенный выше.
В основном, что мы сделаем, так это добавим программно корневой элемент.
Итак, прежде всего вам нужно открыть ресурс, содержащий ваш "искаженный" xml (т. е. файл):
Filefile = newFile(pathtofile);
Затем откройте FileInputStream:
FileInputStreamfis=newFileInputStream(file);
Если мы попытаемся разобрать этот поток с помощью любой библиотеки XML, в этот момент мы вызовем исключение с искаженным документом.
Теперь мы создаем список объектов InputStream с тремя элементами:
Элемент ByteIputStream, содержащий строку: <root>
Наш FileInputStream
ByteInputStream со строкой: </root>
Итак, код:
List<InputStream> streams = Arrays.asList( new ByteArrayInputStream("<root>".getBytes()), fis, new ByteArrayInputStream("</root>".getBytes()));
Теперь, используя SequenceInputStream, мы создаем контейнер для списка, созданного выше:
Теперь мы можем использовать любую библиотеку синтаксического анализа XML в cntr, и она будет проанализирована без каких-либо проблем. (Проверено с помощью библиотеки Stax);