iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 21
0

write xml

這邊介紹的是使用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>

read xml

讀取剛剛建立的 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

iterparse

如果遇到很大的 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

上一篇
python day20(csv、json)
下一篇
python day22(concurrency、parallelism)
系列文
python 自學30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言