python 中使用ElementTree操作XML
概述
? ? ? 對比其他 Python 處理 XML 的方案,xml.etree.ElementTree 模塊(下文我們以 ET 來表示)相對來說比較簡單,接口也較友好。?官方文檔 里面對 ET 模塊進行了較為詳細的描述,總的來說,ET 模塊可以歸納為三個部分:ElementTree類,Element類以及一些操作 XML 的函數Func。?
XML 可以看成是一種樹狀結構,ET 使用ElementTree類來表示整個 XML 文檔,使用Element類來表示 XML 的一個結點。對整 XML 文檔的操作一般是對ElementTree對象進行,而對 XML 結點的操作一般是對Element對象進行。
使用XML時,一般引入一個ET庫,xml.etree.ElementTree(ET簡而言之)
XML的操作可以理解為增刪改查的過程,依據概述中的總體思路,判斷是對XML文檔操作還是對結點進行操作
1、解析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>按照ElementTree操作文件,Element操作對象的思路;ET 模塊支持從一個 XML 文件構造ElementTree對象,使用 ET 模塊的parse()函數來從指定的 XML 文件構造一個ElementTree對象:
#-*-encoding:utf-8-*-import xml.etree.ElementTree as ET# 獲取 XML 文檔對象 ElementTree tree = ET.parse('country_data.xml')# 獲取 XML 文檔對象的根結點 Element root = tree.getroot() # 打印根結點的名稱 print("根節點的名稱:",root.tag) #獲取其他屬性 print('root的屬性:',root.attrib)2、解析XML對象
解析XML對象使用Element。
ET 模塊的fromstring()函數提供從 XML 字符串構造一個Element對象的功能。
xml_str = ET.tostring(root) print("根節點tostring:",xml_str) root = ET.fromstring(xml_str) print("根節點的tag:",root.tag)for child in root:print('root的其他屬性:',child.tag,child.attrib)print(root[0][1].text) print(root[0][2].text)輸出為:
root的其他屬性: country {'name': 'Liechtenstein'}
root的其他屬性: country {'name': 'Singapore'}
root的其他屬性: country {'name': 'Panama'}
2008
141100
使用 ET 模塊的tostring()函數來將上面我們構造的root對象轉化為字符串,注意這里的“字符串”不同于python中的str,然后使用fromstring()函數重新構造一個Element對象,并賦值給root變量,這時root代表整個 XML 文檔的根結點。
3、構造XML
使用ET 模塊的?Element類以及SubElement()函數。?可以使用Element類來生成一個Element對象作為根結點(XML對象),然后使用ET.SubElement()函數生成子結點(結點對象)。
parent = ET.Element('parent') child1 = ET.SubElement(parent,'child1') child1.text = 'leehan.cpm'child2 = ET.SubElement(parent,'child2') child2.attrib['greeting']='hello world'child3 = ET.SubElement(parent,'child2') child2.text="www.baidu.com"xml_str = ET.tostring(parent,encoding='UTF-8') print(xml_str) with open("newxml1.xml",'w') as f:f.write(str(xml_str)) # 如果需要輸出到文件中,可以繼續使用ElementTree.write()方法來處理: tree = ET.ElementTree(parent) tree.write("newxml2.xml",encoding='utf-8')由于使用write寫入的時候規定類型為str,寫入后發可以使用nodpad打開,但是使用瀏覽器打開時顯示為空,因此使用ElementTree.write()方法來處理
<?xml version="1.0"?>-<parent><child1>leehan.cpm</child1><child2 greeting="hello world"/><child3>www.baidu.com</child3></parent>4、XML結點查找與更新
? ?Element類提供了Element.iter()方法來查找指定的結點。Element.iter()會遞歸查找所有的子結點,以便查找到所有符合條件的結點。
# 獲取 XML 文檔對象 ElementTree tree = ET.parse('data.xml') # 獲取 XML 文檔對象的根結點 Element root = tree.getroot() # 遞歸查找所有的 neighbor 子結點 for neighbor in root.iter('neighbor'):print neighbor.attrib輸出結果:
{'direction': 'E', 'name': 'Austria'} {'direction': 'W', 'name': 'Switzerland'} {'direction': 'N', 'name': 'Malaysia'}如果使用Element.findall()或者Element.find()方法,則只會從結點的直接子結點中查找,并不會遞歸查找。
for country in root.findall('country'):rank = country.find('rank').textname = country.get('name')print name, rank5、更新XML結點
如果需要更新結點的文本,可以通過直接修改Element.text來實現。如果需要更新結點的屬性,可以通過直接修改Element.attrib來實現。?對結點進行更新后,可以使用ElementTree.write()方法將更新后的 XML 文檔寫入文件中。
# 獲取 XML 文檔對象 ElementTree tree = ET.parse('example.xml') # 獲取 XML 文檔對象的根結點 Element root = tree.getroot() for rank in root.iter('rank'):new_rank = int(rank.text) + 1rank.text = str(new_rank)rank.attrib['updated'] = 'yes' tree.write('output.xml', encoding='UTF-8')或者使用set設置對象的值,注意這里的set用于設置屬性的值,而不是設置text的值。使用remove刪除元素的值
tree = ET.parse("country_data.xml") root = tree.getroot() for rank in root.iter('rank'):rank.text = str(int(rank.text) + 1)rank.attrib['updatedrank'] = 'updated rank.com' for year in root.iter('year'):year.set('updatedyear','update year.com')tree.write('update.xml')for country in root.findall('country'):gdppc = int(country.find('gdppc').text)if gdppc < 50000:root.remove(country)tree.write('remove.xml')update.xml為
<?xml version="1.0"?>-<data>-<country name="Liechtenstein"><rank updatedrank="updated rank.com">2</rank><year updatedyear="update year.com">2008</year><gdppc>141100</gdppc><neighbor name="Austria" direction="E"/><neighbor name="Switzerland" direction="W"/></country>-<country name="Singapore"><rank updatedrank="updated rank.com">5</rank><year updatedyear="update year.com">2011</year><gdppc>59900</gdppc><neighbor name="Malaysia" direction="N"/></country>-<country name="Panama"><rank updatedrank="updated rank.com">69</rank><year updatedyear="update year.com">2011</year><gdppc>13600</gdppc><neighbor name="Costa Rica" direction="W"/><neighbor name="Colombia" direction="E"/></country></data>remove.xml
<?xml version="1.0"?>-<data>-<country name="Liechtenstein"><rank updatedrank="updated rank.com">2</rank><year updatedyear="update year.com">2008</year><gdppc>141100</gdppc><neighbor name="Austria" direction="E"/><neighbor name="Switzerland" direction="W"/></country>-<country name="Singapore"><rank updatedrank="updated rank.com">5</rank><year updatedyear="update year.com">2011</year><gdppc>59900</gdppc><neighbor name="Malaysia" direction="N"/></country></data>使用append更新元素的值
#使用append更新 newEle0 = ET.Element('newBuildElement') newEle1 = ET.Element('newBuildElement') newEle2 = ET.Element('newBuildElement') newEle0.set('name',"This is a new Element") newEle1.text = "This is a new Element" newEle1.attrib = {'name':"ren",'age':'26'} newEle2.set("'name':'ren','age':'26'","This is a new Element") root.append(newEle0) root.append(newEle1) root.append(newEle2)tree.write('append.xml')6.XML帶有命名空間
<?xml version='1.0' encoding='UTF-8'?> <nvd xmlns="namesapce test"> <data><country1 name="Liechtenstein"><rank>1</rank><year>2008</year><gdppc>141100</gdppc><tag1>temp</tag1><neighbor name="Austria" direction="E"/><neighbor name="Switzerland" direction="W"/></country1><country2 name="中國"><rank2>68</rank2><year2>2011</year2><gdppc2>13600</gdppc2><neighbor2 name="趙三" direction="西邊"/><neighbor2 name="李四" direction="東北"/></country2> </data> </nvd> import xml.etree.ElementTree as ET # 獲取 XML 文檔對象 ElementTree tree = ET.parse('websit.xml')namsespceVar = "{namesapce test}"for index in root.iter("neighbor"):print "index.text", index.attrib運行時會報錯提示當前節點無此屬性
AttributeError: 'NoneType' object has no attribute 'text'在 XML 中,元素名稱是由開發者定義的,當兩個不同的文檔使用相同的元素名時,就會發生命名沖突,而XML 命名空間提供避免元素命名沖突的方法。XML 命名空間屬性被放置于元素的開始標簽之中,并使用以下的語法:
xmlns:namespace-prefix="namespaceURI"當命名空間被定義在元素的開始標簽中時,所有帶有相同前綴的子元素都會與同一個命名空間相關聯。
注釋:用于標示命名空間的地址不會被解析器用于查找信息。其惟一的作用是賦予命名空間一個惟一的名稱。
除了顯式定義,為元素定義默認的命名空間可以讓我們省去在所有的子元素中使用前綴的工作。也就是說所有沒有前綴的標簽都會帶有默認的命名空間,請使用下面的語法:
xmlns="namespaceURI"如下所示
import xml.etree.ElementTree as ETtree = ET.parse('websit.xml')namsespceVar = "{namesapce test}"root = tree.getroot() # var = ET.tostring(root)for index in root.iter(namsespceVar+"neighbor"):index.text = "{}".format(u"修改后結果")print "index.text", index.attribtree.write("countryResult.xml",encoding="UTF-8")重新寫入的結果展示如下:
但是發現每一個節點前面都加了ns0,那如何處理成節點前不要ns0的情形呢?
使用ET.register_namespace()函數
import xml.etree.ElementTree as ET # 獲取 XML 文檔對象 ElementTree tree = ET.parse('websit.xml')namsespceVar = "{namesapce test}"#注冊命名空間 ET.register_namespace("","namesapce test")# # 獲取 XML 文檔對象的根結點 Element root = tree.getroot()for index in root.iter(namsespceVar+"neighbor"):index.text = "{}".format(u"修改后結果")print "index.text", index.attribtree.write("countryResult.xml",encoding="UTF-8")保存后發現解決了上述問題。
7.XML遍歷與應用
一個XML文件,想要通過傳遞參數改變XML中結點的text值
如的xml文件中,想要把neighbor結點中的text值進行修改。
import xml.etree.ElementTree as ETtree = ET.parse('websit.xml')namsespceVar = "{namesapce test}" ET.register_namespace("","namesapce test")root = tree.getroot()def chanage(kwargs={}):for key in kwargs.keys():for index in root.iter(namsespceVar+key):index.text = "{}".format(kwargs[key])tree.write("countryResult.xml",encoding="UTF-8")if __name__ == '__main__':key = {"neighbor":u"改正結果4"}chanage(key)修改后的xml文件為:
<?xml version='1.0' encoding='UTF-8'?> <nvd xmlns="namesapce test"> <data><country1 name="Liechtenstein"><rank>1</rank><year>2008</year><gdppc>141100</gdppc><tag1>temp</tag1><neighbor direction="E" name="Austria">改正結果4</neighbor><neighbor direction="W" name="Switzerland">改正結果4</neighbor></country1><country2 name="中國"><rank2>68</rank2><year2>2011</year2><gdppc2>13600</gdppc2><neighbor2 direction="西邊" name="趙三" /><neighbor2 direction="東北" name="李四" /></country2> </data> </nvd>?
總結
以上是生活随笔為你收集整理的python 中使用ElementTree操作XML的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python使用MySQL数据库
- 下一篇: websocket python爬虫_p