当前位置:  开发笔记 > 编程语言 > 正文

在Python中解析大型XML文档的最快方法是什么?

如何解决《在Python中解析大型XML文档的最快方法是什么?》经验,为你挑选了4个好方法。

我目前正在根据Python Cookbook的第12.5章运行以下代码:

from xml.parsers import expat

class Element(object):
    def __init__(self, name, attributes):
        self.name = name
        self.attributes = attributes
        self.cdata = ''
        self.children = []
    def addChild(self, element):
        self.children.append(element)
    def getAttribute(self,key):
        return self.attributes.get(key)
    def getData(self):
        return self.cdata
    def getElements(self, name=''):
        if name:
            return [c for c in self.children if c.name == name]
        else:
            return list(self.children)

class Xml2Obj(object):
    def __init__(self):
        self.root = None
        self.nodeStack = []
    def StartElement(self, name, attributes):
        element = Element(name.encode(), attributes)
        if self.nodeStack:
            parent = self.nodeStack[-1]
            parent.addChild(element)
        else:
            self.root = element
        self.nodeStack.append(element)
    def EndElement(self, name):
        self.nodeStack.pop()
    def CharacterData(self,data):
        if data.strip():
            data = data.encode()
            element = self.nodeStack[-1]
            element.cdata += data
    def Parse(self, filename):
        Parser = expat.ParserCreate()
        Parser.StartElementHandler = self.StartElement
        Parser.EndElementHandler = self.EndElement
        Parser.CharacterDataHandler = self.CharacterData
        ParserStatus = Parser.Parse(open(filename).read(),1)
        return self.root

我正在处理大小约1 GB的XML文档.有谁知道解析这些更快的方法?



1> Steen..:

我看起来好像你不需要程序中的任何DOM功能.我会先使用(c)ElementTree库.如果使用cElementTree模块的iterparse函数,则可以通过xml工作并在事件发生时处理它们.

但请注意,Fredriks建议使用cElementTree iterparse函数:

要解析大文件,您可以在处理完元素后立即删除元素:

for event, elem in iterparse(source):
    if elem.tag == "record":
        ... process record elements ...
        elem.clear()

上述模式有一个缺点; 它不会清除根元素,因此您最终会得到一个包含许多空子元素的元素.如果您的文件很大,而不是很大,这可能是个问题.要解决这个问题,您需要掌握根元素.最简单的方法是启用启动事件,并保存对变量中第一个元素的引用:

# get an iterable
context = iterparse(source, events=("start", "end"))

# turn it into an iterator
context = iter(context)

# get the root element
event, root = context.next()

for event, elem in context:
    if event == "end" and elem.tag == "record":
        ... process record elements ...
        root.clear()

该lxml.iterparse()不允许这样.



2> bhadra..:

你试过cElementTree模块吗?

cElementTree包含在Python 2.5及更高版本中,作为xml.etree.cElementTree.参考基准.

删除了死的ImageShack链接



3> Manuel Ceron..:

我建议你使用lxml,它是libxml2库的python绑定,非常快.

根据我的经验,libxml2和expat具有非常相似的性能.但我更喜欢libxml2(和python的lxml),因为它似乎更积极地开发和测试.libxml2还有更多功能.

lxml主要与xml.etree.ElementTree API兼容.并且其网站​​上有很好的文档.


lxml是规则!:)

4> Aaron Digull..:

注册回调会极大地减慢解析速度。[EDIT]这是因为(快速)C代码必须调用速度不如C的python解释器。基本上,您正在使用C代码(快速)读取文件,然后在Python中构建DOM (慢)。[/ EDIT]

尝试使用xml.etree.ElementTree,它在C中100%实现,并且可以解析XML而没有对python代码的任何回调。

解析文档后,您可以对其进行过滤以获取所需的内容。

如果那仍然太慢并且您不需要DOM,则另一个选择是将文件读入字符串并使用简单的字符串操作来处理它。

推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有