python 解析xml格式_【TensorFlow】Python解析xml文件

最近在项目中使用TensorFlow训练目标检测模型,在制作自己的数据集时使用了labelimg软件对图片进行标注,产生了VOC格式的数据,但标注生成的xml文件标签值难免会产生个别错误造成程序无法跑通,或后期有修改xml中标签值的需求,所以得使用Python代码对xml文件进行解析操作,当然也是参考了各种博客,故在此总结一下。

1. xml文件格式

由labelimg标注生成的xml文件格式如下所示,

images1

0.png

C:\Users\White\Desktop\images1\0.png

Unknown

1080

1920

3

0

box

Unspecified

0

0

345

673

475

825

box

Unspecified

0

0

609

1095

759

1253

xml是可扩展标记语言,主要用来标记数据和定义数据类型,从结构上看,有以下特点:

只有一个根结点,其中结点中可以有属性;

一个结点由标签对组成,如;

结点的标签对可以有属性,如;

标签对中可以存储数据,如123;

结点可以相互嵌套,形成子结点,如  box;

2.xml.dom解析xml

文件对象模型(Document Object Model,简称DOM),dom在解析xml文件时一次性将整个文档加载至内存,在内存中使用树结构来保存xml文件中的标签元素和结构,同时你可以使用dom中的函数来解析获取文件信息或修改保存信息,以下为使用dom统计某个文件夹下xml文件中每类标签数量的Python代码,

#coding:utf-8

importos.pathimportxml.dom.minidom

class_nums= {"box": 0, "person": 0}

n=0

xmldir= "E:\\Project\\object\\merged_xml"

for xmlfile inos.listdir(xmldir):print(xmlfile)#打开xml文件

dom =xml.dom.minidom.parse(os.path.join(xmldir, xmlfile))#获得元素对象

root =dom.documentElement

name_length= len(root.getElementsByTagName('name'))#获取标签对name之间的值

for i inrange(name_length):

key= str(root.getElementsByTagName('name')[i].firstChild.data)#print(key)

if key inclass_nums.keys():

class_nums[key]+= 1

#print('node', root.getElementsByTagName('filename')[0].firstChild.data)

#print('node', filename.firstChild.data)

n += 1

print('processed file number is', n)for key inclass_nums:print(key, ':', class_nums[key])

1. 导入Python中的xml.dom文件解析模块

import xml.dom.minidom

2. 获取dom对象和结点:xml.dom.minidom是Python用于处理xml文件的模块,其具有函数xml.dom.minidom.parse()

dom = xml.dom.minidom.parse(os.path.join(xmldir, xmlfile))

该函数传入xml文件的路径和文件名的字符串,用于打开一个xml文件,并得到dom文档树,并通过documentElement得到根结点,

root = dom.documentElement

name_length = len(root.getElementsByTagName('name'))

如果我们知道结点的名称,可以通过root.getElementsByTagName('  ')来获得所有名称等于传入字符串的结点,并可以通过索引来获得相同名称的不同结点,如下所示,

name0 = root.getElementsByTagName('name')[0]

name1 = root.getElementsByTagName('name')[1]

4. 获取标签对之间的数据:firstChild 属性返回被选节点的第一个子节点,.data表示获取该节点的数据。

key = str(root.getElementsByTagName('name')[i].firstChild.data)

5. 补充:获取标签的属性值getAttribute(),以前面的123为例,

objectlist = root.getElementsByTagName('object')

object0=objectlist[0]

id0=object0.getAttribute("id")

3.xml.etree.ElementTree解析xml

ElementTree也是处理xml文件的模块,其具有两种类型,python实现型的xml.etree.ElementTree和c语言实现型的xml.etree.cElementTree,后者比前者的速度更快,内存消耗更少。以下为将xml文件转换为CSV文件的代码示例,

#coding:utf-8

importosimportglobimportpandas as pdimportxml.etree.ElementTree as ETdefxml_to_csv(path):

xml_list=[]for xml_file in glob.glob(path + '/*.xml'):#返回解析树

tree =ET.parse(xml_file)#获取根节点

root =tree.getroot()#print(root)

#根据标签名查找root下的所有标签,并获取其值

print(root.find('filename').text)#对所有目标进行解析

for member in root.findall('object'):

value= (root.find('filename').text,

int(root.find('size')[0].text), #width

int(root.find('size')[1].text), #height

member[0].text, #object name

int(member[4][0].text), #xmin

int(float(member[4][1].text)), #ymin

int(member[4][2].text), #xmax

int(member[4][3].text) #ymax

)

xml_list.append(value)

column_name= ['filename', 'width', 'height', 'class', 'xmin', 'ymin', 'xmax', 'ymax']#pandas创建带列名的二维数据表

xml_df = pd.DataFrame(xml_list, columns=column_name)return xml_df

1.首先导入解析模块,

import xml.etree.ElementTree as ET

2. 返回解析树和获取根节点,

#返回解析树

tree =ET.parse(xml_file)#获取根节点

root = tree.getroot()

3. 可以通过根节点root可以遍历下一层的节点,.tag和.attrib可以获取标签名和标签属性,.text获取标签中的值,

for rootChild inroot:print( 'tagname:', rootChild.tag, 'attribute:', rootChild.attrib, 'value:', rootChild.text)

4. 可以使用下标访问各层节点,

int(member[4][0].text), #xmin

int(float(member[4][1].text)), #ymin

5. 使用findall()查找所有相同标签名的标签,

#根据标签名查找root下的所有标签

objectList = root.findall("object")

6.通过set和get来修改标签属性名,

object0 = root.findall('object')[0]

id= object0.get('id')

object0.set('id', 111)

id2= object0.get('id')print (id, id2)

4. 其他解析方式

还可以通过xml.sax模块来解析xml,但前两者已经足够应付大部分需求,在这里就不展开介绍了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值