這邊介紹的是使用xml.etree.ElementTree
模組來處理 xml,將 dictionary 資料
>>> data = {'id' : '1','name' : 'Allen','age' : '20','tel' : '0981382910'}
轉成 xml.格式如下 :
<student>
<id>1</id>
<name>Allen</name>
<age>20</age>
<tel>0981382910</tel>
</student>
先 import xml.etree.ElementTree
模組
>>> from xml.etree.ElementTree import Element
先建立 xml.etree.ElementTree 的 Element 物件,產生的就是最外層的 <student></student>
>>> elem = Element('student')
接著在建立 student tag 底下的 Element,將 dictionary key 和 value 轉成 xml 的 Element (sub_elem).並給 tag (k) 和 value (v) 然後將 element append 到 elem 這物件裡.
>>> for k,v in data.items():
... sub_elem = Element(k)
... sub_elem.text = str(v)
... elem.append(sub_elem)
...
>>> type(elem)
<class 'xml.etree.ElementTree.Element'>
可以透過 ElementTree 的 tostring 將 Element 轉成 string bytes 印出.
>>> from xml.etree.ElementTree import tostring
>>> tostring(elem)
b'<student><id>1</id><name>Allen</name><age>20</age><tel>0981382910</tel></student>'
接著透過 open 把 xml 的內容寫出到檔案裡,由於是 bytes 所以必須使用 open 的 wb
mode.
elem_str = tostring(elem)
>>> with open('student1.xml','wb') as f:
... f.write(elem_str)
...
81
檢查產生的 xml.
> cat student1.xml
<student><id>1</id><name>Allen</name><age>20</age><tel>0981382910</tel></student>
讀取剛剛建立的 xml 檔,也是使用xml.etree.ElementTree
模組.
>>> import xml.etree.ElementTree as et
使用 parse 將 xml 轉成 ElementTree.
>>> students_xml = et.parse('student1.xml')
>>> type(students_xml)
<class 'xml.etree.ElementTree.ElementTree'>
透過 getroot 取得最外層,也就是 student.
>>> students_ele = students_xml.getroot()
>>> type(students_ele)
<class 'xml.etree.ElementTree.Element'>
>>> print(students_ele.tag)
student
再把 student 下一層各 element 的 tag 跟 text 取出.
>>> for elem in students_ele:
... print(elem.tag,elem.text)
...
id 1
name Allen
age 20
tel 0981382910
如果遇到很大的 xml,不想要一次把整個 xml 讀進 memory 可以使用 iterparse,只處理需要的部分.
<students>
<student>
<id>1</id>
<name>Allen</name>
<age>20</age>
<tel>0981382910</tel>
</student>
<student>
<id>2</id>
<name>Andy</name>
<age>25</age>
<tel>0988657009</tel>
</student>
<student>
<id>3</id>
<name>Daniel</name>
<age>30</age>
<tel>0972476017</tel>
</student>
<student>
<id>4</id>
<name>Jack</name>
<age>18</age>
<tel>0933765889</tel>
</student>
<student>
<id>5</id>
<name>Sam</name>
<age>28</age>
<tel>0978901387</tel>
</student>
</students>
找出大於 20 歲的學生有幾位,使用 parse 的方式,會一次把整個 xml 讀進 memory,可能會導致 memory 不足.
>>> count = 0
>>> students_xml = et.parse('students.xml')
>>> for elem in students_xml.iter(tag='age'):
... if int(elem.text) > 20:
... count += 1
...
>>> print(count)
3
改用 iterparse 的方式避開一次把整個檔案讀取進來,events 可以給 start、end、start-ns 和 end-ns 四種參數(ns 是指 xml 的 namespace).start 是指 <age>
而 end 是指 </age>
.
>>> count = 0
>>> for event, elem in et.iterparse('students.xml' , events=("end",)):
... if elem.tag == 'age' and int(elem.text) > 20:
... count += 1
...
>>> print(count)
3
events start
代表遇到 <age>
start tag 就會觸發一次要執行的程式,而 end
代表遇到</age>
end tag 就會觸發一次要執行的程式.所以如果 events start、end 兩個都給的話,一個人就會被 count 兩次,答案就變 6 了.
>>> count = 0
>>> for event, elem in et.iterparse('students.xml' , events=("start","end")):
... if elem.tag == 'age' and int(elem.text) > 20:
... count += 1
...
>>> print(count)
6