python批量修改xml屬性的實(shí)現(xiàn)方式
今天來(lái)說(shuō)說(shuō)xml那些事兒.如何批量修改指定文件夾下的xml文件的指定屬性.分三步走,首先,我們先看看如何讀寫(xiě)單個(gè)
的xml文件;第二步,來(lái)看看如何遍歷指定文件夾下的所有文件,獲取到所有文件的文件名;第三步,我們來(lái)看看一二之間
該如何銜接.好,lets do it
step1:對(duì)單個(gè)xml文件進(jìn)行讀寫(xiě)
給定一個(gè)xml文件:
<?xml version='1.0' encoding='utf-8'?><catalog> <maxid>4</maxid> <login username='pytest' passwd=’123456’> <caption>Python</caption> <item id='4'> <caption>測(cè)試</caption> </item> </login> <item id='2'> <caption>Zope</caption> </item></catalog>
來(lái)看看代碼,怎么讀取里面的屬性(大家先照著注釋理解一遍,有空我再來(lái)詳細(xì)說(shuō)明)
#coding=utf-8import xml.dom.minidom #打開(kāi)xml文檔dom=xml.dom.minidom.parse(’test.xml’) #得到文檔元素對(duì)象root=dom.documentElementprint root.nodeNameprint root.nodeValueprint root.nodeTypeprint root.ELEMENT_NODE #1.獲取maxid 這一node名字(沒(méi)有屬性值),如何獲取里面的文本?bb=root.getElementsByTagName(’maxid’)b=bb[0]print b.nodeName #2.獲取login 這一node名字及相關(guān)屬性值login=root.getElementsByTagName(’login’)login=login[0] #獲取login的相關(guān)屬性值un=login.getAttribute('username')print unpd=login.getAttribute('passwd')print pd#修改先關(guān)屬性值 #3.獲取節(jié)點(diǎn)名為item的相關(guān)屬性值item=root.getElementsByTagName(’item’) #獲取了所有名字為item的nodeitem=item[0] #拿到第一個(gè)item,獲取相關(guān)屬性值i=item.getAttribute('id')#獲取id的值print i #4.獲取標(biāo)簽對(duì)之間的數(shù)據(jù),并修改為新的值caption=root.getElementsByTagName(’caption’)c0=caption[0]print c0.firstChild.data #firstChild屬性返回被選節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn),.data表示獲取該節(jié)點(diǎn)數(shù)據(jù) c1=caption[1]print c1.firstChild.data c2=caption[2] #caption節(jié)點(diǎn)有三個(gè)!!!print c2.firstChild.data#修改標(biāo)簽對(duì)之間的數(shù)據(jù),直接對(duì)節(jié)點(diǎn)數(shù)據(jù)賦值c2.firstChild.data=’dhhdlh’print c2.firstChild.data
好了,看完了demo,我們現(xiàn)在來(lái)實(shí)戰(zhàn)操練一番,使用通用的VOC2007標(biāo)注數(shù)據(jù)集,xml文件長(zhǎng)這個(gè)樣子:
<annotation verified='no'> <folder>row_img</folder> <filename>000002</filename> <path>/home/nvidia/labelImg-master/img_change/row_img/000002.jpg</path> <source> <database>Unknown</database> </source> <size> <width>1200</width> <height>800</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>qwe</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>513</xmin> <ymin>265</ymin> <xmax>921</xmax> <ymax>663</ymax> </bndbox> </object> <object> <name>wieoiwpe</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>513</xmin> <ymin>265</ymin> <xmax>921</xmax> <ymax>663</ymax> </bndbox> </object></annotation>
那么,我們?cè)撊绾涡薷哪?#63;請(qǐng)看:
#coding=utf-8import xml.dom.minidom ###批量讀取xml文件 ###讀取單個(gè)xml文件dom=xml.dom.minidom.parse(’000002.xml’) root=dom.documentElement #獲取標(biāo)簽對(duì)name/pose之間的值name=root.getElementsByTagName(’name’)pose=root.getElementsByTagName(’pose’)#原始信息print ’原始信息’n0=name[0]print n0.firstChild.datan1=name[1]print n1.firstChild.data p0=pose[0]print p0.firstChild.datap1=pose[1]print p1.firstChild.data #修改標(biāo)簽對(duì)之間的值n0.firstChild.data=’circle’n1.firstChild.data=’circle’ p0.firstChild.data=’ok’p1.firstChild.data=’ok’#打印輸出print ’修改后的 name’print n0.firstChild.dataprint n1.firstChild.dataprint ’修改后的 pose’print p0.firstChild.dataprint p1.firstChild.data
好了,現(xiàn)在我們學(xué)會(huì)了如何對(duì)單個(gè)文件進(jìn)行修改,那么多個(gè)文件呢?
step2:遍歷指定路徑下的文件:
#coding=utf-8import osimport os.pathimport xml.dom.minidom path='/home/nvidia/xmlReader/xml/'files=os.listdir(path) #得到文件夾下所有文件名稱s=[]for xmlFile in files: #遍歷文件夾 if not os.path.isdir(xmlFile): #判斷是否是文件夾,不是文件夾才打開(kāi) print xmlFile
(path下我放的是幾個(gè)xml文件),打印xmlFile我們發(fā)現(xiàn)是這樣的:
看到?jīng)],看到這個(gè)的話就說(shuō)明我們已經(jīng)成功一半了!!!接下來(lái)我們把之前寫(xiě)的讀取單個(gè)xml文件的代碼放進(jìn)去
#coding=utf-8import osimport os.pathimport xml.dom.minidom path='/home/nvidia/xmlReader/xml/'files=os.listdir(path) #得到文件夾下所有文件名稱s=[]for xmlFile in files: #遍歷文件夾 if not os.path.isdir(xmlFile): #判斷是否是文件夾,不是文件夾才打開(kāi) print xmlFile #TODO #xml文件讀取操作 #將獲取的xml文件名送入到dom解析 dom=xml.dom.minidom.parse(xmlFile) root=dom.documentElement #獲取標(biāo)簽對(duì)name/pose之間的值 name=root.getElementsByTagName(’name’) pose=root.getElementsByTagName(’pose’) #原始信息 print ’原始信息’ n0=name[0] print n0.firstChild.data n1=name[1] print n1.firstChild.data p0=pose[0] print p0.firstChild.data p1=pose[1] print p1.firstChild.data
直接運(yùn)行,報(bào)錯(cuò)!!我...
不要急,我們一點(diǎn)點(diǎn)來(lái)解決,,遇到問(wèn)題是很正常的嘛!!!首先我們看看遇到什么錯(cuò)?
打印除了000001.xml但是在實(shí)際讀取的時(shí)候出錯(cuò)了!!還說(shuō)找不到在這個(gè)文件?why??仔細(xì)想想發(fā)現(xiàn),這里可能要傳入的是
每個(gè)xml文件的具體路徑,有了這個(gè)想法之后我們?cè)賮?lái)看看:
這個(gè)時(shí)候就設(shè)涉及到Python路徑拼接的知識(shí)了:
path='/home/nvidia/xmlReader/xml/'xmlFile也是幾個(gè)字符串os.path.join(path,xmlFile)#os.path.join('/home/test','test.xml')
那么,我們就拼接好了.然后就執(zhí)行看看:
啊哈?!居然對(duì)了!!哈哈哈,大功告成!接下來(lái)就是先將圖像分好類,然后就可以批量修改文件了
好了,讓我們開(kāi)看看最終的代碼:
#coding=utf-8import osimport os.pathimport xml.dom.minidom path='/home/nvidia/xmlReader/xml/'files=os.listdir(path) #得到文件夾下所有文件名稱s=[]for xmlFile in files: #遍歷文件夾 if not os.path.isdir(xmlFile): #判斷是否是文件夾,不是文件夾才打開(kāi) print xmlFile #TODO #xml文件讀取操作 #將獲取的xml文件名送入到dom解析 dom=xml.dom.minidom.parse(os.path.join(path,xmlFile)) ###最核心的部分,路徑拼接,輸入的是具體路徑 root=dom.documentElement #獲取標(biāo)簽對(duì)name/pose之間的值 name=root.getElementsByTagName(’name’) pose=root.getElementsByTagName(’pose’) #原始信息 print ’原始信息’ n0=name[0] print n0.firstChild.data p0=pose[0] print p0.firstChild.data #修改 n0.firstChild.data=’circle’ p0.firstChild.data=’ok’ #打印輸出 print ’修改后的 name’ print n0.firstChild.data print ’修改后的 pose’ print p0.firstChild.data print ’~~~~~’
其實(shí),就我個(gè)人來(lái)講,還有個(gè)需求,就是文件匹配:根據(jù)A文件夾中的文件名,在B文件夾匹配同名但不同格式的文件,然后將他們單獨(dú)
拎出來(lái),復(fù)制到C文件夾保存,具體該怎么做呢?下一篇博客即將揭曉,拭目以待.
******************2018.1.27更新*******************
上面說(shuō)的方法基于我們已經(jīng)知道了xml文件中有幾個(gè)pose屬性幾個(gè)object屬性,但是一般在修改之前我們是不知道的,那么如何自動(dòng)的去識(shí)別并修改每個(gè)屬性的值呢?接下來(lái)我們開(kāi)看看
這里要用到一個(gè)重要的關(guān)系:Python中的迭代(不同于c++/C,不能寫(xiě)成for i in len(object))而要寫(xiě)成
for i in range(len(pose)):print pose[i].firstChild.data
這樣的話,即使我們不知道有幾處要修改的地方,但是我們都能夠找出來(lái),修改掉(這里每個(gè)pose都修改成同樣的屬性)
修改后,還需要保存到xml文件,修改后的代碼為:
#coding=utf-8import osimport os.pathimport xml.dom.minidom path='/home/nvidia/xmlReader/xml/'files=os.listdir(path) #得到文件夾下所有文件名稱s=[]for xmlFile in files: #遍歷文件夾 if not os.path.isdir(xmlFile): #判斷是否是文件夾,不是文件夾才打開(kāi) print xmlFile #TODO #xml文件讀取操作 #將獲取的xml文件名送入到dom解析 dom=xml.dom.minidom.parse(os.path.join(path,xmlFile)) ###最核心的部分os.path.join(path,xmlFile),路徑拼接,輸入的是具體路徑 root=dom.documentElement #獲取標(biāo)簽對(duì)name/pose之間的值 name=root.getElementsByTagName(’name’) pose=root.getElementsByTagName(’pose’) #重命名class name for i in range(len(name)): print name[i].firstChild.data name[i].firstChild.data=’circle’ print name[i].firstChild.data for j in range(len(pose)): print pose[j].firstChild.data pose[j].firstChild.data=’ok’ print pose[j].firstChild.data #保存修改到xml文件中 with open(os.path.join(path,xmlFile),’w’) as fh: dom.writexml(fh) print(’寫(xiě)入name/pose OK!’) # with open(’dom_write.xml’,’w’,encoding=’UTF-8’) as fh:# # 4.writexml()第一個(gè)參數(shù)是目標(biāo)文件對(duì)象,第二個(gè)參數(shù)是根節(jié)點(diǎn)的縮進(jìn)格式,第三個(gè)參數(shù)是其他子節(jié)點(diǎn)的縮進(jìn)格式,# # 第四個(gè)參數(shù)制定了換行格式,第五個(gè)參數(shù)制定了xml內(nèi)容的編碼。# dom.writexml(fh,indent=’’,addindent=’t’,newl=’n’,encoding=’UTF-8’)# print(’寫(xiě)入xml OK!’)
以上這篇python批量修改xml屬性的實(shí)現(xiàn)方式就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. XML入門(mén)精解之結(jié)構(gòu)與語(yǔ)法2. CSS Hack大全-教你如何區(qū)分出IE6-IE10、FireFox、Chrome、Opera3. CSS3實(shí)例分享之多重背景的實(shí)現(xiàn)(Multiple backgrounds)4. 利用CSS3新特性創(chuàng)建透明邊框三角5. XML入門(mén)的常見(jiàn)問(wèn)題(一)6. HTML5 Canvas繪制圖形從入門(mén)到精通7. 概述IE和SQL2k開(kāi)發(fā)一個(gè)XML聊天程序8. HTML <!DOCTYPE> 標(biāo)簽9. HTML DOM setInterval和clearInterval方法案例詳解10. XML入門(mén)的常見(jiàn)問(wèn)題(二)
