什么是Python的优秀XML流解析器?



是否有用于Python的XML解析器可以解析文件流?我的XML文件太大,内存无法容纳,所以我需要解析流。

理想情况下,我不需要有root访问权限来安装东西,所以lxml不是一个很好的选择。

我一直在使用xml.etree.ElementTree,但我确信它是坏的

这是关于xml.etree.ElementTree.iterparse在大型XML文件上的实践的好答案。lxml也有这种方法。使用iterparse进行流解析的关键是手动清除和删除已经处理的节点,否则最终会耗尽内存。

另一个选择是使用xml.sax。官方手册对我来说太正式了,而且缺少例子,所以它需要和问题一起澄清。默认解析器模块xml.sax.expatreader,实现增量解析接口xml.sax.xmlreader.IncrementalParser。也就是说xml.sax.make_parser()提供了合适的流解析器。

例如,给定如下XML流:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <entry><a>value 0</a><b foo='bar' /></entry>
  <entry><a>value 1</a><b foo='baz' /></entry>
  <entry><a>value 2</a><b foo='quz' /></entry>
  ...
</root>

可以按以下方式处理。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import xml.sax

class StreamHandler(xml.sax.handler.ContentHandler):
  lastEntry = None
  lastName  = None

  def startElement(self, name, attrs):
    self.lastName = name
    if name == 'entry':
      self.lastEntry = {}
    elif name != 'root':
      self.lastEntry[name] = {'attrs': attrs, 'content': ''}
  def endElement(self, name):
    if name == 'entry':
      print({
        'a' : self.lastEntry['a']['content'],
        'b' : self.lastEntry['b']['attrs'].getValue('foo')
      })
      self.lastEntry = None
    elif name == 'root':
      raise StopIteration
  def characters(self, content):
    if self.lastEntry:
      self.lastEntry[self.lastName]['content'] += content

if __name__ == '__main__':
  # use default ``xml.sax.expatreader``
  parser = xml.sax.make_parser()
  parser.setContentHandler(StreamHandler())
  # feed the parser with small chunks to simulate
  with open('data.xml') as f:
    while True:
      buffer = f.read(16)
      if buffer:
        try:
          parser.feed(buffer)
        except StopIteration:
          break
  # if you can provide a file-like object it's as simple as
  with open('data.xml') as f:
    parser.parse(f)

您正在寻找xml.sax吗?

使用xml.etree.cElementTree。它比xml.etree.ElementTree快得多。它们都没有坏。你的文件坏了(见我对你的另一个问题的回答)。

相关内容

  • 没有找到相关文章

最新更新