XML parsing - ElementTree vs SAX and DOM
python有几种解析XML的方法…
我了解使用SAX解析的基本知识。它使用事件驱动的API作为流解析器。
我也理解DOM解析器。它将XML读取到内存中,并将其转换为可以用Python访问的对象。
一般来说,根据需要做的事情、内存限制、性能等,在两者之间进行选择是很容易的。
(希望到目前为止我是正确的。)
自从python 2.5以来,我们也有elementtree。这与dom和sax相比如何?它与哪个更相似?为什么它比以前的解析器更好?
ElementTree更易于使用,因为它将XML树(基本上)表示为列表结构,属性表示为字典。
与DOM相比,elementtree需要的XML树内存要少得多(因此速度更快),并且通过
与完整的XML库相比,与Python2.5中的elementTree只有一个很小的特性集,但对于许多应用程序来说已经足够了。如果您需要一个验证解析器或完整的XPath支持,那么LXML就是解决问题的方法。很长一段时间以来,它一直很不稳定,但我从2.1开始就没有遇到任何问题。
elementtree与dom不同,后者中的节点可以访问其父节点和同级节点。处理实际文档而不是数据存储也有点麻烦,因为文本节点不被视为实际节点。在XML代码段中
1 | This is a test |
字符串
一般来说,我建议将elementtree作为使用python进行所有XML处理的默认值,并将dom或sax作为特定问题的解决方案。
最小DOM实现:
链接。
python提供了完整的W3C标准的XML DOM(xml.dom)实现和最小的XML.dom.minidom实现。后者比完整的实现更简单、更小。但是,从"解析角度"来看,它具有标准DOM的所有优点和缺点,即它将所有内容加载到内存中。
考虑到基本的XML文件:
1 2 3 4 5 6 7 8 9 10 11 | <?xml version="1.0"?> <catalog> <book isdn="xxx-1"> A1</author> T1 </book> <book isdn="xxx-2"> A2</author> T2 </book> </catalog> |
使用minidom的一个可能的python解析器是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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中不支持它!
元素树XML API:链接。
elementtree更易于使用,它比XMLDOM需要更少的内存。此外,还提供了C实现(xml.etree.CelementTree)。
使用elementtree的一个可能的python解析器是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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 |
elementTree的parse()类似于dom,而iterparse()类似于sax。在我看来,elementtree比dom和sax更好,因为它提供了更容易使用的API。
elementtree有更多的pythonic API。它现在也在标准库中,因此使用它可以减少依赖性。
实际上,我更喜欢LXML,因为它有类似API的elementtree,但也有很好的附加特性和良好的性能。