系统城装机大师 - 固镇县祥瑞电脑科技销售部宣传站!

当前位置:首页 > 脚本中心 > python > 详细页面

python批量修改xml属性的实现方式

时间:2020-03-05来源:电脑系统城作者:电脑系统城

今天来说说xml那些事儿.如何批量修改指定文件夹下的xml文件的指定属性.分三步走,首先,我们先看看如何读写单个

的xml文件;第二步,来看看如何遍历指定文件夹下的所有文件,获取到所有文件的文件名;第三步,我们来看看一二之间

该如何衔接.好,lets do it

step1:对单个xml文件进行读写

给定一个xml文件:


 
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <catalog>
  3. <maxid>4</maxid>
  4. <login username="pytest" passwd='123456'>
  5.   <caption>Python</caption>
  6. <item id="4">
  7. <caption>测试</caption>
  8. </item>
  9. </login>
  10. <item id="2">
  11. <caption>Zope</caption>
  12. </item>
  13. </catalog>

来看看代码,怎么读取里面的属性(大家先照着注释理解一遍,有空我再来详细说明)


 
  1. #coding=utf-8
  2. import xml.dom.minidom
  3.  
  4. #打开xml文档
  5. dom=xml.dom.minidom.parse('test.xml')
  6.  
  7. #得到文档元素对象
  8. root=dom.documentElement
  9. print root.nodeName
  10. print root.nodeValue
  11. print root.nodeType
  12. print root.ELEMENT_NODE
  13.  
  14. #1.获取maxid 这一node名字(没有属性值),如何获取里面的文本?
  15. bb=root.getElementsByTagName('maxid')
  16. b=bb[0]
  17. print b.nodeName
  18.  
  19. #2.获取login 这一node名字及相关属性值
  20. login=root.getElementsByTagName('login')
  21. login=login[0] #获取login的相关属性值
  22. un=login.getAttribute("username")
  23. print un
  24. pd=login.getAttribute("passwd")
  25. print pd
  26. #修改先关属性值
  27.  
  28.  
  29. #3.获取节点名为item的相关属性值
  30. item=root.getElementsByTagName('item') #获取了所有名字为item的node
  31. item=item[0] #拿到第一个item,获取相关属性值
  32. i=item.getAttribute("id")#获取id的值
  33. print i
  34.  
  35. #4.获取标签对之间的数据,并修改为新的值
  36. caption=root.getElementsByTagName('caption')
  37. c0=caption[0]
  38. print c0.firstChild.data #firstChild属性返回被选节点的第一个子节点,.data表示获取该节点数据
  39.  
  40. c1=caption[1]
  41. print c1.firstChild.data
  42.  
  43. c2=caption[2] #caption节点有三个!!!
  44. print c2.firstChild.data
  45. #修改标签对之间的数据,直接对节点数据赋值
  46. c2.firstChild.data='dhhdlh'
  47. print c2.firstChild.data

好了,看完了demo,我们现在来实战操练一番,使用通用的VOC2007标注数据集,xml文件长这个样子:


 
  1. <annotation verified="no">
  2. <folder>row_img</folder>
  3. <filename>000002</filename>
  4. <path>/home/nvidia/labelImg-master/img_change/row_img/000002.jpg</path>
  5. <source>
  6. <database>Unknown</database>
  7. </source>
  8. <size>
  9. <width>1200</width>
  10. <height>800</height>
  11. <depth>3</depth>
  12. </size>
  13. <segmented>0</segmented>
  14. <object>
  15. <name>qwe</name>
  16. <pose>Unspecified</pose>
  17. <truncated>0</truncated>
  18. <difficult>0</difficult>
  19. <bndbox>
  20. <xmin>513</xmin>
  21. <ymin>265</ymin>
  22. <xmax>921</xmax>
  23. <ymax>663</ymax>
  24. </bndbox>
  25. </object>
  26. <object>
  27. <name>wieoiwpe</name>
  28. <pose>Unspecified</pose>
  29. <truncated>0</truncated>
  30. <difficult>0</difficult>
  31. <bndbox>
  32. <xmin>513</xmin>
  33. <ymin>265</ymin>
  34. <xmax>921</xmax>
  35. <ymax>663</ymax>
  36. </bndbox>
  37. </object>
  38. </annotation>

那么,我们该如何修改呢?请看:


 
  1. #coding=utf-8
  2. import xml.dom.minidom
  3.  
  4. ###批量读取xml文件
  5.  
  6.  
  7.  
  8. ###读取单个xml文件
  9. dom=xml.dom.minidom.parse('000002.xml')
  10.  
  11. root=dom.documentElement
  12.  
  13. #获取标签对name/pose之间的值
  14. name=root.getElementsByTagName('name')
  15. pose=root.getElementsByTagName('pose')
  16. #原始信息
  17. print '原始信息'
  18. n0=name[0]
  19. print n0.firstChild.data
  20. n1=name[1]
  21. print n1.firstChild.data
  22.  
  23. p0=pose[0]
  24. print p0.firstChild.data
  25. p1=pose[1]
  26. print p1.firstChild.data
  27.  
  28. #修改标签对之间的值
  29. n0.firstChild.data='circle'
  30. n1.firstChild.data='circle'
  31.  
  32. p0.firstChild.data='ok'
  33. p1.firstChild.data='ok'
  34. #打印输出
  35. print '修改后的 name'
  36. print n0.firstChild.data
  37. print n1.firstChild.data
  38. print '修改后的 pose'
  39. print p0.firstChild.data
  40. print p1.firstChild.data
  41.  

好了,现在我们学会了如何对单个文件进行修改,那么多个文件呢?

step2:遍历指定路径下的文件:


 
  1. #coding=utf-8
  2. import os
  3. import os.path
  4. import xml.dom.minidom
  5.  
  6. path="/home/nvidia/xmlReader/xml/"
  7. files=os.listdir(path) #得到文件夹下所有文件名称
  8. s=[]
  9. for xmlFile in files: #遍历文件夹
  10. if not os.path.isdir(xmlFile): #判断是否是文件夹,不是文件夹才打开
  11. print xmlFile
  12.  

(path下我放的是几个xml文件),打印xmlFile我们发现是这样的:

python批量修改xml属性的实现方式

看到没,看到这个的话就说明我们已经成功一半了!!!接下来我们把之前写的读取单个xml文件的代码放进去


 
  1. #coding=utf-8
  2. import os
  3. import os.path
  4. import xml.dom.minidom
  5.  
  6. path="/home/nvidia/xmlReader/xml/"
  7. files=os.listdir(path) #得到文件夹下所有文件名称
  8. s=[]
  9. for xmlFile in files: #遍历文件夹
  10. if not os.path.isdir(xmlFile): #判断是否是文件夹,不是文件夹才打开
  11. print xmlFile
  12.  
  13. #TODO
  14. #xml文件读取操作
  15.  
  16. #将获取的xml文件名送入到dom解析
  17. dom=xml.dom.minidom.parse(xmlFile)
  18. root=dom.documentElement
  19. #获取标签对name/pose之间的值
  20. name=root.getElementsByTagName('name')
  21. pose=root.getElementsByTagName('pose')
  22. #原始信息
  23. print '原始信息'
  24. n0=name[0]
  25. print n0.firstChild.data
  26. n1=name[1]
  27. print n1.firstChild.data
  28.  
  29. p0=pose[0]
  30. print p0.firstChild.data
  31. p1=pose[1]
  32. print p1.firstChild.data

直接运行,报错!!我...

不要急,我们一点点来解决,,遇到问题是很正常的嘛!!!首先我们看看遇到什么错?

python批量修改xml属性的实现方式

打印除了000001.xml但是在实际读取的时候出错了!!还说找不到在这个文件?why??仔细想想发现,这里可能要传入的是

每个xml文件的具体路径,有了这个想法之后我们再来看看:

这个时候就设涉及到Python路径拼接的知识了:

path="/home/nvidia/xmlReader/xml/"
xmlFile也是几个字符串
os.path.join(path,xmlFile)
#os.path.join("/home/test","test.xml")

那么,我们就拼接好了.然后就执行看看:

python批量修改xml属性的实现方式

啊哈?!居然对了!!哈哈哈,大功告成!接下来就是先将图像分好类,然后就可以批量修改文件了

python批量修改xml属性的实现方式

好了,让我们开看看最终的代码:


 
  1. #coding=utf-8
  2. import os
  3. import os.path
  4. import xml.dom.minidom
  5.  
  6. path="/home/nvidia/xmlReader/xml/"
  7. files=os.listdir(path) #得到文件夹下所有文件名称
  8. s=[]
  9. for xmlFile in files: #遍历文件夹
  10. if not os.path.isdir(xmlFile): #判断是否是文件夹,不是文件夹才打开
  11. print xmlFile
  12.  
  13. #TODO
  14. #xml文件读取操作
  15.  
  16. #将获取的xml文件名送入到dom解析
  17. dom=xml.dom.minidom.parse(os.path.join(path,xmlFile)) ###最核心的部分,路径拼接,输入的是具体路径
  18. root=dom.documentElement
  19. #获取标签对name/pose之间的值
  20. name=root.getElementsByTagName('name')
  21. pose=root.getElementsByTagName('pose')
  22. #原始信息
  23. print '原始信息'
  24. n0=name[0]
  25. print n0.firstChild.data
  26.  
  27. p0=pose[0]
  28. print p0.firstChild.data
  29.  
  30. #修改
  31. n0.firstChild.data='circle'
  32. p0.firstChild.data='ok'
  33. #打印输出
  34. print '修改后的 name'
  35. print n0.firstChild.data
  36.  
  37. print '修改后的 pose'
  38. print p0.firstChild.data
  39. print '~~~~~'
  40.  

其实,就我个人来讲,还有个需求,就是文件匹配:根据A文件夹中的文件名,在B文件夹匹配同名但不同格式的文件,然后将他们单独

拎出来,复制到C文件夹保存,具体该怎么做呢?下一篇博客即将揭晓,拭目以待.

******************2018.1.27更新*******************

上面说的方法基于我们已经知道了xml文件中有几个pose属性几个object属性,但是一般在修改之前我们是不知道的,那么如何自动的去识别并修改每个属性的值呢?接下来我们开看看

这里要用到一个重要的关系:Python中的迭代(不同于c++/C,不能写成for i in len(object))而要写成

for i in range(len(pose)):
print pose[i].firstChild.data

这样的话,即使我们不知道有几处要修改的地方,但是我们都能够找出来,修改掉(这里每个pose都修改成同样的属性)

修改后,还需要保存到xml文件,修改后的代码为:


 
  1. #coding=utf-8
  2. import os
  3. import os.path
  4. import xml.dom.minidom
  5.  
  6. path="/home/nvidia/xmlReader/xml/"
  7. files=os.listdir(path) #得到文件夹下所有文件名称
  8. s=[]
  9. for xmlFile in files: #遍历文件夹
  10. if not os.path.isdir(xmlFile): #判断是否是文件夹,不是文件夹才打开
  11. print xmlFile
  12.  
  13. #TODO
  14. #xml文件读取操作
  15.  
  16. #将获取的xml文件名送入到dom解析
  17. dom=xml.dom.minidom.parse(os.path.join(path,xmlFile)) ###最核心的部分os.path.join(path,xmlFile),路径拼接,输入的是具体路径
  18. root=dom.documentElement
  19. #获取标签对name/pose之间的值
  20. name=root.getElementsByTagName('name')
  21. pose=root.getElementsByTagName('pose')
  22. #重命名class name
  23. for i in range(len(name)):
  24. print name[i].firstChild.data
  25. name[i].firstChild.data='circle'
  26. print name[i].firstChild.data
  27.  
  28. for j in range(len(pose)):
  29. print pose[j].firstChild.data
  30. pose[j].firstChild.data='ok'
  31. print pose[j].firstChild.data
  32.  
  33. #保存修改到xml文件中
  34. with open(os.path.join(path,xmlFile),'w') as fh:
  35. dom.writexml(fh)
  36. print('写入name/pose OK!')
  37.  
  38.  
  39. # with open('dom_write.xml','w',encoding='UTF-8') as fh:
  40. # # 4.writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式,
  41. # # 第四个参数制定了换行格式,第五个参数制定了xml内容的编码。
  42. # dom.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
  43. # print('写入xml OK!')

以上这篇python批量修改xml属性的实现方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

分享到:

相关信息

系统教程栏目

栏目热门教程

人气教程排行

站长推荐

热门系统下载