Проблема синтаксического анализа XML - PullRequest
0 голосов
/ 19 февраля 2009

У меня есть синтаксический анализатор XML, который падает на неполных данных XML. Таким образом, данные XML, передаваемые ему, могут быть следующими:

<one><two>twocontent</two</one>

<a/><b/> ( the parser treats it as two root elements )

Атрибуты элемента также обрабатываются (хотя и не показаны выше).

Теперь проблема в том, что когда я читаю данные из сокета, я получаю данные фрагментами. Например:

<one>one

content</two>

</one>

Таким образом, перед отправкой XML в анализатор я должен создать действительный XML и отправить его. Какая программная конструкция (например, итерация, рекурсия и т. Д.) Лучше всего подходит для такого сценария.

Я программирую на C ++.

Пожалуйста, помогите.

Ответы [ 5 ]

7 голосов
/ 19 февраля 2009

Краткий ответ: Вы делаете это неправильно.

Ваш вопрос смешивает две отдельные проблемы:

  1. Синтаксический анализ данных, которые не совсем правильно сформированы. XML , т. Е. Так называемый суп из тегов.

    Пример: файлы, созданные программистами, которые не понимают XML или имеют паршивые методы кодирования.

    • Нечестно сказать: файл, который не является правильно сформированным XML, вообще не является XML-документом. Каждый правильный синтаксический анализатор XML будет отклонять его. В идеале вы должны исправить источник этих данных и убедиться, что вместо этого генерируется правильный XML.

    • В качестве альтернативы используйте анализатор супа тега, то есть анализатор, который выполняет исправление ошибок.

      Полезные парсеры теговых супов часто являются HTML-парсерами. приборка уже была указана в другом ответе.

      Убедитесь, что вы понимаете, какие шаги исправления фактически выполняет такой синтаксический анализатор, поскольку не существует универсального подхода, который мог бы исправить XML. В частности, Tidy очень агрессивен в "восстановлении" данных, более агрессивен, чем реальные браузеры и спецификации HTML 5, например.

  2. Синтаксический анализ XML из сокета , куда данные поступают по частям в потоке. В этой ситуации документ XML можно рассматривать как «бесконечный», причем чанки обрабатываются как внешний вид задолго до того, как будет замечен конечный конечный тег для корневого элемента.

    Пример: XMPP - это протокол, который работает следующим образом.

    • Решение состоит в том, чтобы использовать синтаксический анализатор, основанный на извлечении, например, API XMLTextReader в libxml2.

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

2 голосов
/ 19 февраля 2009

Что передает вам XML с другого конца сокетного соединения? Это не имеет смысла, что вы должны пропустить что-то, как вы иллюстрируете, только потому, что вы получаете это из сокета.

Если сокет использует TCP (или пользовательский протокол с похожими свойствами), вы не должны пропускать части вашего XML. Таким образом, вы должны иметь возможность просто буферизовать все это до тех пор, пока другой конец не сообщит «конец документа», а затем передать его в свой разборчивый анализатор XML.

Если вы используете UDP или какой-либо другой протокол с потерями, вам необходимо пересмотреть его, поскольку, очевидно, невозможно правильно передать большой XML-документ по каналу, который случайно отбрасывает фрагменты.

1 голос
/ 19 февраля 2009

Поскольку структура XML является иерархической структурой (деревом), рекурсия была бы лучшим способом приблизиться к этому. Вы можете вызвать рекурсию для каждого дочернего элемента и исправить недостающие XML-идентификаторы. По сути, вы будете делать то же самое, что и анализатор DOM-объектов, только вы будете анализировать файл, чтобы исправить его структуру. Одна вещь, хотя, мне кажется, что в этом методе вы собираетесь переписать анализатор XML. Разве это не талия времени? Может быть, лучше найти способ придать XML правильную структуру, чем пытаться ее исправить.

0 голосов
/ 19 февраля 2009

В вашем примере, как вы собираетесь выяснить, где именно в контенте разместить открывающий тег <two>, как только вы обнаружите, что он отсутствует? Это, как говорится, нетривиально.

0 голосов
/ 19 февраля 2009

Есть ли несколько авторов? Почему ваш парсер не проверяет XML?

Используйте дерево, где каждый узел представляет элемент и несет с собой грязный бит. Первое вхождение узла помечает его как грязный, т. Е. Вы ожидаете закрывающий тег, если, конечно, узел не имеет форму <a/>. Кроме того, первый элемент, с которым вы сталкиваетесь, - это корень.

Когда вы попадаете на грязный узел, продолжайте помещать узлы в стек до тех пор, пока вы не нажмете на закрывающий тег, когда вы извлекаете содержимое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...