2008-10-10 121 views
64

Python有几种方法来解析XML ...XML解析 - ElementTree的VS SAX和DOM

我明白与SAX解析的非常基本的。它用作流解析器,具有事件驱动的API。

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

一般来说,很容易根据你需要做的,内存限制,性能等

什么2之间选择(希望我是正确为止)。

既然Python 2.5,我们也有ElementTree。这与DOM和SAX相比如何?哪一个更类似于?为什么它比以前的解析器更好?

回答

60

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

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

与Python 2.5相比,ElementTree与完整的XML库相比只有一小部分功能,但对于许多应用程序来说它已足够。如果您需要验证解析器或完整的XPath支持,则需要使用lxml。很长时间以来,它一直很不稳定,但从2.1开始我就没有任何问题。

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

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

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

通常,我推荐ElementTree作为Python的所有XML处理的默认值,DOM或SAX作为特定问题的解决方案。

+0

谢谢你提到以下两个警告! (我碰巧需要在我的项目中)。“XPath支持... ElementTree背离了DOM,其中节点可以访问其父代和兄弟。” – 2014-01-30 20:08:16

8

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

+0

另外,我发现我想要的真实结构,而不是一系列的事件。 – 2008-10-10 20:40:15

+0

串行解析器对于简单解析通常足够好。我使用sax开始使用Python,并且只有当我的需求对于sax来说太复杂时才切换到minidom。我应该补充一点,我还没有使用ElementTree,因为它似乎没有提供足够的功能让我将代码移植到它。 – giltay 2008-10-10 20:58:40

6

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

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

11

最小DOM实现:

链接:http://docs.python.org/2/library/xml.dom.minidom.html#module-xml.dom.minidom

的Python提供了一个完整的,W3C标准的执行XML DOM的(XML。dom)和最小的一个,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> 

一个可能的Python解析器使用minidom命名是:

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是一个Python接口外籍人士非验证XML解析器(docs.python.org/2/library/pyexpat.html)。

xml.dom的包装用品也异常类抛出:DOMException,但它不是supperted在minidom命名

ElementTree的XML API:

链接:http://docs.python.org/2/library/xml.etree.elementtree.html

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