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

Ail*_*lyn 10 python xml parsing stream

有没有可以解析文件流的Python XML解析器?我的XML文件太大,无法容纳在内存中,所以我需要解析流.

理想情况下,我不需要root权限来安装东西,因此lxml不是一个很好的选择.

我一直在使用,xml.etree.ElementTree我确信它已经坏了.

saa*_*aaj 15

这里有很好的答案有关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>
Run Code Online (Sandbox Code Playgroud)

可以通过以下方式处理.

#!/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)
Run Code Online (Sandbox Code Playgroud)


Pet*_*rin 8

你在找xml.sax?它在标准库中是正确的.


Joh*_*hin 1

使用xml.etree.cElementTree。比 快多了xml.etree.ElementTree。它们都没有坏。您的文件已损坏(请参阅我对您的其他问题的回答)。

  • iterparse() 不是也在构建树吗(“请注意,iterparse 仍然构建树,就像解析器一样。”http://effbot.org/zone/element-iterparse.htm)。我的答案是与彼得·维克托林的答案相冲突。 (6认同)
  • 确实,速度要快得多。是的,我的文件被破坏了。 (5认同)
  • 仅供参考:在 2019 年,“cElementTree”只是“ElementTree”的别名。 (2认同)