2009-10-02 2 views
5

Я пытаюсь разобрать * большой файл (> 5 ГБ) структурированных данных разметки. Формат данных по существу является XML, но нет явного корневого элемента. Каков наиболее эффективный способ сделать это?Разбор больших файлов псевдо-xml в python

Проблема с синтаксическими анализаторами SAX заключается в том, что для них требуется корневой элемент, поэтому либо я должен добавить псевдофайл в поток данных (есть ли эквивалент Java SequenceInputStream в Python?), Либо я должен переключиться на анализатор, основанный на не-SAX-совместимости (есть ли преемник sgmllib?)

Структура данных довольно проста. В основном это список элементов:

<Document> 
    <docid>1</docid> 
    <text>foo</text> 
</Document> 
<Document> 
    <docid>2</docid> 
    <text>bar</text> 
</Document> 

* фактически итерацию

ответ

11

http://docs.python.org/library/xml.sax.html

Обратите внимание, что вы можете передать 'поток' объект xml.sax.parse. Это означает, что вы можете передать любой объект с файловыми методами (например, read) на вызов parse ... Создайте свой собственный объект, который сначала поместит ваш виртуальный корневой стартовый тег, затем содержимое файла, затем виртуальный корень конечный тег. Я предполагаю, что вам нужно всего лишь реализовать метод read ... но это может зависеть от саксового парсера, который вы будете использовать.

Пример, который работает для меня:

import xml.sax 
import xml.sax.handler 

class PseudoStream(object): 
    def read_iterator(self): 
     yield '<foo>' 
     yield '<bar>' 
     for line in open('test.xml'): 
      yield line 
     yield '</bar>' 
     yield '</foo>' 

    def __init__(self): 
     self.ri = self.read_iterator() 

    def read(self, *foo): 
     try: 
      return self.ri.next() 
     except StopIteration: 
      return '' 

class SAXHandler(xml.sax.handler.ContentHandler): 
    def startElement(self, name, attrs): 
     print name, attrs 

d = xml.sax.parse(PseudoStream(), SAXHandler()) 
+0

Является 'возвращение '' 'на самом деле то, что нужно делать на' StopIteration'? Как бы клиент этого кода заметил EOF, если он использовал только 'read()' then? –

+4

Одним из свойств потоковых объектов в python является то, что вызов read() блокирует и возвращает хотя бы один байт, или в случае EOF возвращает пустую строку. Вот как работает исходный метод file.read. – liori

+1

Возможно, вы захотите использовать это совместно с PullDOM - он сочетает в себе потоковый характер SAX с иерархической природой DOM. – RichieHindle

1

Быстрый и грязный ответ будет добавить корневой элемент (как строка), так что это будет действительным XML.

С уважением.

1

Добавить корневой элемент и использовать SAX, Stax или VTD-XML ..

+0

Г-н Чжан - хороший ответ. Я поддержал это. –

+0

Я связал учетную запись meta с этим, где 100 очков, которые вы обещали? –

0

xml.parsers.expat - Быстрый синтаксический анализ XML с помощью Expat Модуль xml.parsers.expat представляет собой интерфейс Python к Неправительственный Expat - проверка парсера XML. Модуль предоставляет один тип расширения xmlparser, который представляет текущее состояние анализатора XML. После создания объекта xmlparser различные атрибуты объекта могут быть настроены на функции обработчика. Когда XML-документ затем передается в парсер, функции обработчика вызываются для символьных данных и разметки в документе XML.

Подробнее: http://www.python.org/doc/2.5/lib/module-xml.parsers.expat.html

Смежные вопросы