在Python中解析大型伪XML文件

6 投票
4 回答
2459 浏览
提问于 2025-04-15 14:44

我正在尝试解析一个超过5GB的大文件,这个文件里面是结构化的标记数据。数据格式基本上是XML,但没有明确的根元素。有什么高效的方法可以做到这一点呢?

使用SAX解析器的问题在于,它们需要一个根元素,所以我要么得在数据流中添加一个伪元素(在Python中有没有类似Java的SequenceInputStream的东西?),要么就得换成一个不符合SAX标准的基于事件的解析器(有没有sgmllib的后续版本?)

数据的结构其实很简单。基本上就是一系列元素的列表:

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

*实际上是要进行迭代

4 个回答

1

xml.parsers.expat -- 使用Expat快速解析XML

xml.parsers.expat模块是Python用来与Expat这个不进行验证的XML解析器进行交互的工具。这个模块提供了一种叫做xmlparser的扩展类型,它代表了XML解析器的当前状态。当你创建了一个xmlparser对象后,可以把这个对象的各种属性设置为处理函数。当你把一个XML文档输入到解析器时,这些处理函数会被调用,用来处理XML文档中的字符数据和标记。

更多信息:http://www.python.org/doc/2.5/lib/module-xml.parsers.expat.html

1

添加根元素,然后使用SAX、StAX或VTD-XML等技术。

11

你可以把一个“流”对象传给 xml.sax.parse。这意味着你可以传递任何有类似文件操作的方法的对象,比如 read。你可以自己创建一个对象,先放上一个虚拟的根开始标签,然后是文件的内容,最后再放上虚拟的根结束标签。我想你只需要实现 read 方法……不过这可能还要看你用的 sax 解析器。

下面是一个对我有效的例子:

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())

撰写回答