79

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

我了解使用SAX进行解析的基础知识。它用作流解析器,具有事件驱动的 API。

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

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

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

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

4

4 回答 4

79

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

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

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

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

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

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

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

于 2008-10-11T16:02:41.003 回答
14

最小的 DOM 实现:

链接

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>

一个可能的使用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 解析器 (docs.python.org/2/library/pyexpat.html) 的 Python 接口。

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

ElementTree XML API:

链接

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
于 2013-03-16T17:33:15.727 回答
8

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

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

于 2008-10-11T15:24:41.457 回答
7

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

于 2008-10-10T20:25:05.343 回答