我目前正在根据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文档.有谁知道解析这些更快的方法?
我看起来好像你不需要程序中的任何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()不允许这样.
你试过cElementTree模块吗?
cElementTree包含在Python 2.5及更高版本中,作为xml.etree.cElementTree.参考基准.
删除了死的ImageShack链接
我建议你使用lxml,它是libxml2库的python绑定,非常快.
根据我的经验,libxml2和expat具有非常相似的性能.但我更喜欢libxml2(和python的lxml),因为它似乎更积极地开发和测试.libxml2还有更多功能.
lxml主要与xml.etree.ElementTree API兼容.并且其网站上有很好的文档.
注册回调会极大地减慢解析速度。[EDIT]这是因为(快速)C代码必须调用速度不如C的python解释器。基本上,您正在使用C代码(快速)读取文件,然后在Python中构建DOM (慢)。[/ EDIT]
尝试使用xml.etree.ElementTree,它在C中100%实现,并且可以解析XML而没有对python代码的任何回调。
解析文档后,您可以对其进行过滤以获取所需的内容。
如果那仍然太慢并且您不需要DOM,则另一个选择是将文件读入字符串并使用简单的字符串操作来处理它。