XML解析 - ElementTree vs SAX和DOM

问题描述 投票:68回答:4

Python有几种解析XML的方法......

我理解使用SAX解析的基础知识。它充当流解析器,具有事件驱动的API。

我也理解DOM解析器。它将XML读入内存并将其转换为可以使用Python访问的对象。

一般来说,根据你需要做什么,内存限制,性能等,很容易在两者之间做出选择。

(希望到目前为止我是正确的。)

从Python 2.5开始,我们也有了ElementTree。这与DOM和SAX相比如何?哪个更相似?为什么它比以前的解析器更好?

python xml dom sax elementtree
4个回答
65
投票

ElementTree更容易使用,因为它表示XML树(基本上)作为列表结构,属性表示为字典。

ElementTree需要比DOM更少的内存(因此更快),并且通过iterparse的解析开销与SAX相当。此外,iterparse返回部分结构,并且您可以在解析期间通过在处理结构时立即丢弃结构来保持内存使用不变。

与完整的XML库相比,ElementTree在Python 2.5中只有一个小的功能集,但对于许多应用程序来说已经足够了。如果您需要验证解析器或完整的XPath支持,那么lxml就是您的选择。很长一段时间,它曾经非常不稳定,但自2.1以来我没有遇到任何问题。

ElementTree偏离DOM,其中节点可以访问其父节点和兄弟节点。处理实际文档而不是数据存储也有点麻烦,因为文本节点不被视为实际节点。在XML片段中

<a>This is <b>a</b> test</a>

字符串test将是所谓的tail元素b

一般来说,我建议将ElementTree作为使用Python进行所有XML处理的默认值,并将DOM或SAX作为特定问题的解决方案。


13
投票

Minimal DOM implementation:

Link

Python提供了XML DOM(xml.dom)的完整W3C标准实现和最小的xml.dom.minidom。后者比完整实现更简单,更小。但是,从“解析角度”来看,它具有标准DOM的所有优点和缺点 - 即它将所有内容加载到内存中。

考虑一个基本的XML文件:

<?xml version="1.0"?>
<catalog>
    <book isdn="xxx-1">
      <author>A1</author>
      <title>T1</title>
    </book>
    <book isdn="xxx-2">
      <author>A2</author>
      <title>T2</title>
    </book>
</catalog>

使用minidom的可能的Python解析器是:

import os
from xml.dom import minidom
from xml.parsers.expat import ExpatError

#-------- Select the XML file: --------#
#Current file name and directory:
curpath = os.path.dirname( os.path.realpath(__file__) )
filename = os.path.join(curpath, "sample.xml")
#print "Filename: %s" % (filename)

#-------- Parse the XML file: --------#
try:
    #Parse the given XML file:
    xmldoc = minidom.parse(filepath)
except ExpatError as e:
    print "[XML] Error (line %d): %d" % (e.lineno, e.code)
    print "[XML] Offset: %d" % (e.offset)
    raise e
except IOError as e:
    print "[IO] I/O Error %d: %s" % (e.errno, e.strerror)
    raise e
else:
    catalog = xmldoc.documentElement
    books = catalog.getElementsByTagName("book")

    for book in books:
        print book.getAttribute('isdn')
        print book.getElementsByTagName('author')[0].firstChild.data
        print book.getElementsByTagName('title')[0].firstChild.data

请注意,xml.parsers.expat是Expat非验证XML解析器的Python接口(docs.python.org/2/library/pyexpat.html)。

xml.dom包还提供了异常类DOMException,但minidom不支持它!

The ElementTree XML API:

Link

ElementTree更易于使用,并且它比XML DOM需要更少的内存。此外,还提供了一个C实现(xml.etree.cElementTree)。

使用ElementTree的可能的Python解析器是:

import os
from xml.etree import cElementTree  # C implementation of xml.etree.ElementTree
from xml.parsers.expat import ExpatError  # XML formatting errors

#-------- Select the XML file: --------#
#Current file name and directory:
curpath = os.path.dirname( os.path.realpath(__file__) )
filename = os.path.join(curpath, "sample.xml")
#print "Filename: %s" % (filename)

#-------- Parse the XML file: --------#
try:
    #Parse the given XML file:
    tree = cElementTree.parse(filename)
except ExpatError as e:
    print "[XML] Error (line %d): %d" % (e.lineno, e.code)
    print "[XML] Offset: %d" % (e.offset)
    raise e
except IOError as e:
    print "[XML] I/O Error %d: %s" % (e.errno, e.strerror)
    raise e
else:
    catalogue = tree.getroot()

    for book in catalogue:
        print book.attrib.get("isdn")
        print book.find('author').text
        print book.find('title').text

7
投票

ElementTree的parse()就像DOM,而iterparse()就像SAX。在我看来,ElementTree比DOM和SAX更好,因为它提供了更容易使用的API。


7
投票

ElementTree有更多的pythonic API。它现在也在标准库中,因此使用它可以减少依赖性。

我实际上更喜欢lxml,因为它有像ElementTree这样的API,但也有很好的附加功能,并且运行良好。

© www.soinside.com 2019 - 2024. All rights reserved.