在Python中解析大型伪XML文件
我正在尝试解析一个超过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())