читатель python libxml2 и XML_PARSE_RECOVER - PullRequest
8 голосов
/ 06 октября 2010

Я пытаюсь заставить читателя восстановиться после испорченного XML.Использование опции libxml2.XML_PARSE_RECOVER с API-интерфейсом DOM (libxml2.readDoc) работает и восстанавливает проблемы с сущностями.

Однако используется опция с API-интерфейсом для чтения (что важно из-за размера документов, которые мы анализируем) не работает.Он просто застревает в бесконечном цикле (когда reader.Read () возвращает -1):

Пример кода (с небольшим примером):

import cStringIO
import libxml2

DOC = "<a>some broken & xml</a>"

reader = libxml2.readerForDoc(DOC, "urn:bogus", None, libxml2.XML_PARSE_RECOVER | libxml2.XML_PARSE_NOERROR)

ret = reader.Read()
while ret:
    print 'ret: %d' % ret
    print "node name: ", reader.Name(), reader.NodeType()
    ret = reader.Read()

Есть идеи, как правильно восстановить?

Ответы [ 4 ]

1 голос
/ 30 октября 2010

Я не слишком уверен в текущем состоянии привязок libxml2.Даже сайт libxml2 предлагает вместо этого использовать lxml .Чтобы разобрать это дерево и проигнорировать & - это красиво и чисто в lxml:

from cStringIO import StringIO
from lxml import etree

DOC = "<a>some broken & xml</a>"

reader = etree.XMLParser(recover=True)
tree = etree.parse(StringIO(DOC), reader)
print etree.tostring(tree.getroot())

Страница парсеров в документации lxml содержит более подробную информацию о настройке парсера и итерациипо содержанию.

Редактировать:

Если вы хотите выполнять поэтапный анализ документа, можно также использовать класс XMLparser, поскольку он является подклассом _FeedParser:

DOC = "<a>some broken & xml</a>"
reader = etree.XMLParser(recover=True)

for data in StringIO(DOC).read():
    reader.feed(data)

tree = reader.close()
print etree.tostring(tree)
0 голосов
/ 19 января 2011

Или вы можете использовать BeautifulSoup . Это делает хорошую работу по восстановлению сломанного ML.

0 голосов
/ 16 января 2011

Рассмотрите возможность использования xml.sax.Когда я представляю действительно искаженный XML, в котором может быть множество разных проблем, попробуйте разделить проблему на маленькие кусочки.

Вы упомянули, что у вас очень большой XML-файл, и, вероятно, в нем много записей, которые вы обрабатываете.серийно.И каждая запись (например, <item>...</item> имеет начальный и конечный тег, предположительно - это будут ваши точки восстановления.

В xml.sax вы предоставляете считыватель, обработчик и источники ввода . В худшем случае отдельные записи будут невозможно восстановить с помощью этого метода. Это немного больше настроек, но, вероятно, лучшее, что вы можете сделать, - это постепенно разбирать искаженный фид записи во время регистрации неверных записей.

В журналах убедитесь, что вы предоставили себе достаточно информации для восстановления исходной записи, чтобы вы могли добавить дополнительный код восстановления для всех случаев, которые вам, без сомнения, придется обрабатывать (например, создать badrecords_ today's date .xml, чтобы вы могли выполнить повторную обработку вручную).

Удачи.

0 голосов
/ 30 октября 2010

Разве xml не нарушен каким-то последовательным образом?Есть ли какой-нибудь шаблон, который вы могли бы использовать для восстановления вашего xml перед анализом?

Например, если ошибка вызвана только неэкранированными амперсандами и вы не используете CDATA или инструкции по обработке, ее можно исправить с помощью регулярного выражения.

РЕДАКТИРОВАТЬ:sgmllib в стандартной библиотеке Python.BeautifulSoup использует его, поэтому он может быть полезен в вашем случае.(Сама BeatifulSoup предлагает только представление дерева, а не события).

...