Python中使用ElementTree對(duì)XML文件進(jìn)行解析

Python中使用ElementTree對(duì)XML文件進(jìn)行解析

官方API介紹:https://docs.python.org/3.6/library/xml.etree.elementtree.html

XML文件介紹:

XML指可擴(kuò)展標(biāo)記語(yǔ)言(eXtensible Markup Language)灿里,接觸過(guò)Java或者Android的同學(xué)們相信絕對(duì)不會(huì)陌生呼渣,XML被設(shè)計(jì)用來(lái)傳輸和存儲(chǔ)數(shù)據(jù)站宗,雖然現(xiàn)在用來(lái)與服務(wù)端交互更多情況下使用的都是Json格式的數(shù)據(jù),但是XML格式還是有著廣泛的應(yīng)用。
最近在公司的項(xiàng)目中辙诞,需要使用Python腳本在后臺(tái)對(duì)反編譯的apk文件進(jìn)行合并煞躬,其中對(duì)Manifest文件中標(biāo)簽的處理,主要就是用到了Python中的XML解析聋迎,因此寫(xiě)一篇文章記錄一下脂矫。

Python中提供的XML解析方式:

方法 特點(diǎn)
SAX SAX解析通過(guò)流模式在解析XML的過(guò)程中觸發(fā)對(duì)應(yīng)的事件(start_element、char_data霉晕、end_element)并調(diào)用用戶定義的回調(diào)函數(shù)來(lái)處理XML文件庭再。
DOM 將XML數(shù)據(jù)在內(nèi)存中解析成一個(gè)樹(shù)捞奕,通過(guò)對(duì)樹(shù)的操作來(lái)操作XML,占用內(nèi)存大拄轻,解析速度較慢颅围,優(yōu)點(diǎn)是可以任意遍歷樹(shù)的節(jié)點(diǎn)。
ElementTree 類似一個(gè)輕量級(jí)的DOM恨搓,也是本篇文章主要介紹的院促。

準(zhǔn)備一份XML格式的文件:

巧婦難為無(wú)米之炊,需要進(jìn)行解析斧抱,首先必須有一個(gè)XML文件常拓,本篇文章采用官方API示例中的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>

XML文件格式介紹:

<tag attrib = > text </tag> tail
例:<APP_KEY channel = 'CSDN'> hello123456789 </APP_KEY>

  • tag辉浦,即標(biāo)簽弄抬,用于標(biāo)識(shí)該元素表示哪種數(shù)據(jù),即APP_KEY
  • attrib盏浙,即屬性眉睹,用Dictionary形式保存,即{'channel' = 'CSDN'}
  • text废膘,文本字符串竹海,可以用來(lái)存儲(chǔ)一些數(shù)據(jù),即hello123456789
  • tail丐黄,尾字符串斋配,并不是必須的,例子中沒(méi)有包含灌闺。

ElementTree解析XML文件的過(guò)程:

  • 導(dǎo)入ElementTree艰争,import xml.etree.ElementTree as ET
  • 解析Xml文件找到根節(jié)點(diǎn):
  • 直接解析XML文件并獲得根節(jié)點(diǎn),tree = ET.parse('country_data.xml') root = tree.getroot()
  • 解析字符串桂对,root = ET.fromstring(country_data_as_string)
  • 遍歷根節(jié)點(diǎn)可以獲得子節(jié)點(diǎn)甩卓,然后就可以根據(jù)需求拿到需要的字段了。

源碼演示:

示例代碼:

#蕉斜!usr/bin/python
# -*- coding: utf-8 -*-
#==========================
import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()
print('root-tag:',root.tag,',root-attrib:',root.attrib,',root-text:',root.text)
for child in root:
     print('child-tag是:',child.tag,',child.attrib:',child.attrib,',child.text:',child.text)
     for sub in child:
          print('sub-tag是:',sub.tag,',sub.attrib:',sub.attrib,',sub.text:',sub.text)

運(yùn)行結(jié)果:

>>> 
root-tag: data ,root-attrib: {} ,root-text: 
    
child-tag是: country ,child.attrib: {'name': 'Liechtenstein'} ,child.text: 
        
sub-tag是: rank ,sub.attrib: {} ,sub.text: 1
sub-tag是: year ,sub.attrib: {} ,sub.text: 2008
sub-tag是: gdppc ,sub.attrib: {} ,sub.text: 141100
sub-tag是: neighbor ,sub.attrib: {'direction': 'E', 'name': 'Austria'} ,sub.text: None
sub-tag是: neighbor ,sub.attrib: {'direction': 'W', 'name': 'Switzerland'} ,sub.text: None
child-tag是: country ,child.attrib: {'name': 'Singapore'} ,child.text: 
        
sub-tag是: rank ,sub.attrib: {} ,sub.text: 4
sub-tag是: year ,sub.attrib: {} ,sub.text: 2011
sub-tag是: gdppc ,sub.attrib: {} ,sub.text: 59900
sub-tag是: neighbor ,sub.attrib: {'direction': 'N', 'name': 'Malaysia'} ,sub.text: None
child-tag是: country ,child.attrib: {'name': 'Panama'} ,child.text: 
        
sub-tag是: rank ,sub.attrib: {} ,sub.text: 68
sub-tag是: year ,sub.attrib: {} ,sub.text: 2011
sub-tag是: gdppc ,sub.attrib: {} ,sub.text: 13600
sub-tag是: neighbor ,sub.attrib: {'direction': 'W', 'name': 'Costa Rica'} ,sub.text: None
sub-tag是: neighbor ,sub.attrib: {'direction': 'E', 'name': 'Colombia'} ,sub.text: None

查找指定的子節(jié)點(diǎn):

當(dāng)XML文件較大或者其中的子節(jié)點(diǎn)tag非常多的時(shí)候逾柿,一個(gè)一個(gè)獲取是比較麻煩的而且有很多不是我們需要的,這樣我們可以通過(guò)find('nodeName')或者findall('nodeName')方法來(lái)查找指定tag的節(jié)點(diǎn)宅此。

  • find('nodeName'):表示在該節(jié)點(diǎn)下机错,查找其中第一個(gè)tag為nodeName的節(jié)點(diǎn)。
  • findall('nodeName'):表示在該節(jié)點(diǎn)下父腕,查找其中所有tag為nodeName的節(jié)點(diǎn)弱匪。

代碼示例:

#!usr/bin/python
# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()
animNode = root.find('country') #查找root節(jié)點(diǎn)下第一個(gè)tag為country的節(jié)點(diǎn)
print(animNode.tag,animNode.attrib,animNode.text)

運(yùn)行結(jié)果,可以在XML文件中看到璧亮,第一個(gè)tag為country的節(jié)點(diǎn)確實(shí)是Liechtenstein:

>>> 
country {'name': 'Liechtenstein'} 

刪除指定的節(jié)點(diǎn)以及保存

在合并Manifest文件的時(shí)候萧诫,可能有一些重復(fù)的權(quán)限斥难,那么怎么刪除掉呢,刪除指定節(jié)點(diǎn)可以通過(guò)remove(node)方法,移除指定的節(jié)點(diǎn)财搁。
代碼示例蘸炸,比如我們想移除attribute中name為L(zhǎng)iechtenstein的節(jié)點(diǎn):

#!usr/bin/python
# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()
animNode = root.find('country') 
if animNode.attrib['name'] == 'Liechtenstein':
     root.remove(animNode)
tree.write('finish.xml')#保存修改后的XML文件

運(yùn)行結(jié)果,我們打開(kāi)保存的finish.xml文件尖奔,發(fā)現(xiàn)保存結(jié)果如下搭儒,name為L(zhǎng)iechtenstein的節(jié)點(diǎn)已經(jīng)被刪除了:

<data>
    <country name="Singapore">
        <rank>4</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank>68</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市提茁,隨后出現(xiàn)的幾起案子淹禾,更是在濱河造成了極大的恐慌,老刑警劉巖茴扁,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铃岔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡峭火,警方通過(guò)查閱死者的電腦和手機(jī)毁习,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)卖丸,“玉大人纺且,你說(shuō)我怎么就攤上這事∩越” “怎么了载碌?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)衅枫。 經(jīng)常有香客問(wèn)我嫁艇,道長(zhǎng),這世上最難降的妖魔是什么弦撩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任步咪,我火速辦了婚禮,結(jié)果婚禮上益楼,老公的妹妹穿的比我還像新娘歧斟。我一直安慰自己,他們只是感情好偏形,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著觉鼻,像睡著了一般俊扭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坠陈,一...
    開(kāi)封第一講書(shū)人閱讀 51,692評(píng)論 1 305
  • 那天萨惑,我揣著相機(jī)與錄音捐康,去河邊找鬼。 笑死庸蔼,一個(gè)胖子當(dāng)著我的面吹牛解总,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播姐仅,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼花枫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了掏膏?” 一聲冷哼從身側(cè)響起劳翰,我...
    開(kāi)封第一講書(shū)人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎馒疹,沒(méi)想到半個(gè)月后佳簸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡颖变,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年生均,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腥刹。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡马胧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肛走,到底是詐尸還是另有隱情漓雅,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布朽色,位于F島的核電站邻吞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏葫男。R本人自食惡果不足惜抱冷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望梢褐。 院中可真熱鬧旺遮,春花似錦、人聲如沸盈咳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鱼响。三九已至鸣剪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筐骇。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工债鸡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人铛纬。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓厌均,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親告唆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子棺弊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容