Python 標准庫之 xml.etree.ElementTree
Python中有多種xml處理API,常用的有xml.dom.*模塊、xml.sax.*模塊、xml.parser.expat模塊和xml.etree.ElementTree模塊(以下簡稱ET)。本文將主要介紹ET的使用,以及它的常用函數。其它模塊的簡介,請參照文獻[1]。
ET使用Element表示xml中的節點、文本、注釋等。其主要屬性如下:
tag:string對象,表示數據代表的種類,當為節點時為節點名稱。 text:string對象,表示element的內容。 attrib:dictionary對象,表示附有的屬性。 tail:string對象,表示element閉合之后的尾跡。 若干子元素(child elements)。
<tag attrib1=1>text</tag>tail
1 3 2 4
1 3 2 4
PS: ET模塊對於那些惡意構造的數據並不是安全的,如果需要解析數據最好了一下xml的弱點[2]
一、導入ET
在Python標准庫中,ElementTree有兩種實現方式:一種是純Python的實現xml.etree.ElementTree,另一種是速度更快一點的xml.etree.cElementTree。如果不確定環境中是否有cElementTree,可以使用如下的方式導入:
try: import xml.etree.cElementTree as ET except ImportError: import xml.etree.ElementTree as ET
但從Python 3.3開始,會默認使用cElementTree來加快速度,但是之前的版本最好使用如上的代碼,以提高代碼的兼容性。
二、解析xml
假設我們現在有如下的xml
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
有兩種方式可以解析xml
1. 從文件中解析xml文件
>>> import xml.etree.cElementTree as ET >>> tree = ET.ElementTree(file='doc1.xml') #載入數據
>>> root = tree.getroot() #獲取根節點
<Element 'doc' at 0x11eb780>
2. 從內存字符串中解析xml
root = ET.fromstring(country_data_as_string)
其中第二種方式可以直接過去根節點。
三、數據的訪問
>>> for child in root: ... print child.tag, child.attrib ... country {'name': 'Liechtenstein'} country {'name': 'Singapore'} country {'name': 'Panama'}
或者直接使用索引尋找子節點:
>>> root[0][1].text '2008'
或者使用xpath方式進行遍歷,但其支持部分xpath方法,其支持的xpath請參照[4]
>>> root.findall("./country/neighbor") [<Element 'neighbor' at 0x14fa0f0>, <Element 'neighbor' at 0x14fa150>, <Element 'neighbor' at 0x14fa3f0>, <Element 'neighbor' at 0x14fa6c0>, <Element 'neighbor' at 0x14fa750>]
四、 處理xml流
如下的程序將從xml文件中一邊讀入xml一邊解析,並將在遇到標簽開始或標簽結束的時候返回相應的事件。
for event, elem in ET.iterparse(sys.argv[2]): if event == 'end': if elem.tag == 'location' and elem.text == 'Zimbabwe': count += 1 elem.clear() # discard the element
這個程序將在檢查到標簽結束的時候,對指定的標簽進行計數。最后的elem.clear()保證了,在解析的之后盡快的釋放內存。
五、Element對象
class xml.etree.ElementTree.Element(tag, attrib={}, **extra) tag:string 元素代表的數據種類。 text:string 元素的內容。 tail:string 元素的尾形。 attrib:dictionary 元素的屬性字典。 #針對屬性的操作 clear() 清空元素的后代、屬性、text和tail也設置為None。 get(key, default=None) 獲取key對應的屬性值,如該屬性不存在則返回default值。 items() 根據屬性字典返回一個列表,列表元素為(key, value)。 keys() 返回包含所有元素屬性鍵的列表。 set(key, value) 設置新的屬性鍵與值。 #針對后代的操作 append(subelement) 添加直系子元素。 extend(subelements) 增加一串元素對象作為子元素。#python2.7新特性 find(match) 尋找第一個匹配子元素,匹配對象可以為tag或path。 findall(match) 尋找所有匹配子元素,匹配對象可以為tag或path。 findtext(match) 尋找第一個匹配子元素,返回其text值。匹配對象可以為tag或path。 insert(index, element) 在指定位置插入子元素。 iter(tag=None) 生成遍歷當前元素所有后代或者給定tag的后代的迭代器。#python2.7新特性 iterfind(match) 根據tag或path查找所有的后代。 itertext() 遍歷所有后代並返回text值。 remove(subelement) 刪除子元素。
六、ElementTree對象
class xml.etree.ElementTree.ElementTree(element=None, file=None) element如果給定,則為新的ElementTree的根節點。 _setroot(element):用給定的element替換當前的根節點。慎用。 # 以下方法與Element類中同名方法近似,區別在於它們指定以根節點作為操作對象。 find(match) findall(match) findtext(match, default=None) iter(tag=None) iterfind(match) parse(source, parser=None) 裝載xml對象,source可以為文件名或文件類型對象 getroot() 獲取根節點 write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None,method="xml")
七、模塊方法-->用於生成xml文件
1. 創建一個特別的element,通過標准序列化使其代表了一個comment。comment可以為bytestring或unicode。
ET.Comment(text=None)
ET.dump(elem)
3. text是一個包含XML數據的字符串,與XML()方法類似,返回一個Element實例。
4. 從字符串的序列對象中解析xml文檔。缺省parser為XMLParser,返回Element實例。V2.7中新加屬性
5. 檢查是否是一個element對象。
ET.fromstring(text)
ET.fromstringlist(sequence, parser=None)
ET.iselement(element)
注意,iterparse()只會在看見開始標簽的">"符號時才會拋出start事件,因此屆時屬性是已經定義了,但是text和tail屬性在那時還沒有定義,同樣子元素也沒有定義,因此他們可能不能被顯示出來。如果你想要完整的元素,請查找end事件。
ET.iterparse(source, events=None, parser=None)
ET.parse(source, parser=None)
ET.ProcessingInstruction(target, text=None)
ET.register_namespace(prefix, uri)
ET.SubElement(parent, tag, attrib={}, **extra)
ET.tostring(element, encoding="us-ascii", method="xml")
ET.tostringlist(element, encoding="us-ascii", method="xml")
ET.XML(text, parser=None)
14. 從字符串常量解析出xml片段,同時返回一個字典,用以映射element的id到其自身。
ET.XMLID(text, parser=None)
