Python解析xml
XML 被設計用來傳輸和存儲數據。
HTML 被設計用來顯示數據。
XML(eXtensible Markup Language)指可擴展標記語言,被設計用來傳輸和存儲數據,已經日趨成為當前許多新生技術的核心,在不同的領域都有著不同的應用。它是web發展到一定階段的必然產物,既具有SGML的核心特征,又有著HTML的簡單特性,還具有明確和結構良好等許多新的特性。
python解析XML常見的有三種方法:一是xml.dom.*模塊,它是W3C DOM API的實現,若需要處理DOM API則該模塊很適合,註意xml.dom包裏面有許多模塊,須區分它們間的不同;二是xml.sax.*模塊,它是SAX API的實現,這個模塊犧牲了便捷性來換取速度和內存占用,SAX是一個基於事件的API,這就意味著它可以“在空中”處理龐大數量的的文檔,不用完全加載進內存;三是xml.etree.ElementTree模塊(簡稱 ET),它提供了輕量級的Python式的API,相對於DOM來說ET 快了很多,而且有很多令人愉悅的API可以使用,相對於SAX來說ET的ET.iterparse也提供了 “在空中” 的處理方式,沒有必要加載整個文檔到內存,ET的性能的平均值和SAX差不多,但是API的效率更高一點而且使用起來很方便。
Python解析xml的三種方式為:Element tree、DOM、SAX
Element tree:
Element類型是一種靈活的容器對象,用於在內存中存儲層次數據結構。可以說是list和dictionary的交叉,它生來就是為了處理XML,它在Python標準庫中有兩種實現:一種是純Python實現的,如xml.etree.ElementTree,另一種是速度快一點的xml.etree.cElementTree。註意:盡量使用C語言實現的那種,因為它速度更快,而且消耗的內存更少。
Element tree會將xml文件解析為元素樹。
每個element都有一系列相關屬性:
- 標簽,用於標識該元素表示哪種數據(即元素類型)
- 一些屬性,存儲在Python dictionary中
- 一個文本字符串
- 一個可選的尾字符串
- 一些孩子elements,存儲在Python sequence中
abc.xml文件如下
<?xml version="1.0"?> <!--主節點為data 孩子節點為country,也就是二級tag--> <data> <country name="Singapore" area="Asia"> <rank>4</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor name="Malaysia" direction="N"/> </country> <country name="Panama" area="NA"> <rank>68</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> </data>
使用Element tree解析的python代碼如下:
import xml.etree.ElementTree as ET #在這裏還可以使用c實現的 速度更快,寫法如下
‘‘‘try:
import xml.etree.ElementTree as ET
except ImportError:
import xml.etree.cElementTree as ET‘‘‘
import sys try: tree = ET.parse(‘abc.xml‘) #打開xml文件生成解析對象 # root = ET.fromstring(‘xml字符串‘) #解析xml字符串時,解析函數生成元素樹 root = tree.getroot() #得到根節點 except Exception as e: print(‘parse object error‘) sys.exit(1) print(root.tag, "---", root.attrib) #root.tag值為data,而列屬性attrib不存在值 for child in root: #遍歷子節點 print(child.tag, "---", child.attrib) #child節點的tag屬性,子節點的列屬性存在值 print("*"*10) print(‘year:‘+root[0][1].text) #root[0]為第一個子節點:第一個country print(root[0].tag, root[0][1].text) # root[0]的意思是第一個子節點的tag屬性, 所以root[0][1].text意思就是:訪問文本內容得到第一個子節點的第二個標簽數據,這種方法是通過根節點來得到的,還可以通過根節點的遍歷查找拿到。 print("*"*10) for cons in root.findall(‘country‘): #從根節點開始遍歷尋找country節點 rank = cons.find(‘rank‘).text #想拿到子節點中rank標簽對嵌入的值 neighbor = cons.find(‘neighbor‘).get(‘name‘) # 查找country中neighbor這個tag ,然後再拿到列中name屬性 name = cons.get(‘name‘) #子節點的get方法直接拿到列中想要的屬性 area = cons.get(‘area‘) #同上 print(‘country:‘+name+‘\narea:‘+area+‘\nranking:‘+rank+‘\nneighbor:‘+neighbor+‘\n‘)
結果如下:
data --- {} country --- {‘name‘: ‘Singapore‘, ‘area‘: ‘Asia‘} country --- {‘name‘: ‘Panama‘, ‘area‘: ‘NA‘} ********** year:2011 country 2011 ********** country:Singapore area:Asia ranking:4 neighbor:Malaysia country:Panama area:NA ranking:68 neighbor:Costa Rica
同時Element還可以叠代遍歷子樹:
for country in root.iter(‘country‘): print(country.attrib) #同時叠代出的字樹也可以拿到列屬性,
#name = country.get(‘name‘)
#不僅一個列可以拿到,相同子節點所有文本內容都可拿到....
#rank = country.find(‘rank‘).text
for neighbor in root.iter(‘neighbor‘): print(neighbor.attrib)
結果:
{‘name‘: ‘Singapore‘, ‘area‘: ‘Asia‘} {‘name‘: ‘Panama‘, ‘area‘: ‘NA‘} {‘name‘: ‘Malaysia‘, ‘direction‘: ‘N‘} {‘name‘: ‘Costa Rica‘, ‘direction‘: ‘W‘} {‘name‘: ‘Colombia‘, ‘direction‘: ‘E‘}
ElementTree.write() 提供了修改xml文件的方法
#此處剔除排名大於50的國家 for country in root.iter(‘country‘): rank = int(country.find(‘rank‘).text) if rank > 50: root.remove(country) tree.write(‘output.xml‘)
結果另一個country字樹被剔除,output.xml如下:
如何修改子節點中標簽的屬性?
修改rank排名。每個國家前進一名
#使每個國家排名前進一名 for rank in root.iter(‘rank‘): # uprank = int() print(rank.text) uprank = int(rank.text) - 1 rank.text = str(uprank) tree.write(‘out.xml‘)
結果
還可以為標簽添加屬性
for rank in root.iter(‘rank‘): # uprank = int() print(rank.text) uprank = int(rank.text) - 1 rank.text = str(uprank) rank.set(‘after_modify‘, ‘success‘) #使用set方法即可修改 tree.write(‘out.xml‘)
out.xml
<data> <country area="Asia" name="Singapore"> <rank after_modify="success">3</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor direction="N" name="Malaysia" /> </country> <country area="NA" name="Panama"> <rank after_modify="success">67</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor direction="W" name="Costa Rica" /> <neighbor direction="E" name="Colombia" /> </country> </data>
細則參見官方文檔:xml.etree.ElementTree
DOM和SAX可以參考其他的博客
Python解析xml