2008-10-10 158 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