1. 程式人生 > >Python解析xml

Python解析xml

w3c dir nts 所有 parse data 效率 數據結構 htm

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