Python读取、修改、保存xml文件

  在做目标检测的时候,我们获取到图片的xml文件,我们想利用xml文件来解析得到我们想要的信息。或者我们想要对xml文件做一些修改,下面我将利用Python中自带的xml包来完成这一系列的操作(其实还有一个用于解析HTML的包lxml也可以解析xml文件,也非常好用的,具体使用方法可以参看这篇博客)。参考网站我放在的底部,里面讲得也很详细。本文利用来演示的xml模板结构如下图:

  

一、读取并解析xml文件

  我们主要使用的模块是xml.etree.ElementTree

 1、解析xml——获取xml树  

import xml.etree.ElementTree as ET
file_xml = '/home/g4/桌面/project/xxxx/99.xml'  # xml文件路径
tree = ET.parse(file_xml)
type(tree)
xml.etree.ElementTree.ElementTree

   这里的tree的对象是ElementTree,从名字也可以知道这个数据结构类似于多叉树,我们可以通过dir()来查看这个类的属性和方法。

dir(tree)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_root', '_setroot', 'find', 'findall', 'findtext', 'getiterator', 'getroot', 'iter', 'iterfind', 'parse', 'write', 'write_c14n']

  我们这里可以看到里面有find方法,findall方法,之后会讲到,使用方式。

  我们接下来要获取其根节点,以及其他节点的内容。

 2、解析xml——获取子节点及其节点内容

  获得一棵树之后我们,我们通过tree的getroot()方法来获得整颗树的根结点

root = tree.getroot()
type(root)
xml.etree.ElementTree.Element
dir(root)
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'attrib', 'clear', 'extend', 'find', 'findall', 'findtext', 'get', 'getchildren', 'getiterator', 'insert', 'items', 'iter', 'iterfind', 'itertext', 'keys', 'makeelement', 'remove', 'set', 'tag', 'tail', 'text']

  我们可以看到根结点的数据类型是Element,其实这棵树的所有节点数据类型都是Element,下面介绍这些方法和属性

  1. root.find('xxx'):返回的是一个Element对象,也就是在该节点下提取出叫做‘xxx’这个字节点(如果有多个叫做xxx的子节点,将会返回首个)
  2. root.findall('xxx'):返回值是一个列表,列表的每个元素是Element,也就是返回该节点下叫做‘xxx’的所有子节点,用list来储存
  3. root.attrib : 返回该Element所有的“属性”,是一个字典,该节点的“属性”就是<里面id,name这些东西>,一会可以结合示例xml文件,看到具体的返回值。
  4. root.text: 返回一个字符串,是这个根节点的所包含的内容(也就是<obj>xxxx<obj>中的xxxx)

  接下来我们就根据着文章开头的示例xml,来展示一下以上介绍到的方法和属性

path = root.find('path')  # 获取root节点(annotation)下的叫做path的这个节点
type(path)
xml.etree.ElementTree.Element
root.attrib  # 获取annotation节点的属性(包含有两个属性一个是name,一个是id)
{'name': 'Panama', 'id': '1234'}
path.text   # 获取path节点的内容
'百度'
root.findall('object')  
[<Element 'object' at 0x7fd9adcec110>, <Element 'object' at 0x7fd9adcecbf0>]

  可以看到第一行中我们获取了root的字节点path,path也是一个Element的类别,因此它也是有上面提到的那些方法和属性的。

  我们可以看一下最后一行命令,返回的这个列表,里面储存的元素显示的是节点的内存地址。我们前面提到tree也是有findall方法的,其实如果使用tree的findall('object')得到的结果也是一样的。

tree.findall('object')
[<Element 'object' at 0x7fd9adcec110>, <Element 'object' at 0x7fd9adcecbf0>]

  我们可以看到内存地址也是一样的,因此这两种方式来搜索得到子节点是一模一样的。

二、修改xml文件

  我们已经可以提取xml中的信息了,接下来我们可以修改获取到的xml文件里的信息。

 1、修改节点内容

  如果要修改节点的内容我们可以直接使用Element.text = 'xxxx',就就可以完成修改了。

path.text = '修改后'
path = root.find('path')
path.text
'修改后'

  上面的例子显示path节点的text已经从原来的‘百度’变成了‘修改后’,并且在重新从root中获取path节点,也是显示修改之后的结果。因此修改节点内容是非常方简单的。

 2、修改节点属性

  新增节点属性。Element.set(新属性名,新值)

root.set('sex', '')
root.attrib
{'name': 'Panama', 'id': '1234', 'sex': ''}

  修改节点的属性,也是使用Element中的set方法。Element.set(待修改的属性名,新值)

root.set('id', '4321')
root.attrib
{'name': 'Panama', 'id': '4321', 'sex': ''}

  可以看到root的id这个属性已经被修改成了4321。

  (删除属性值,我还没找到对应的方法。。。。)

 3、删除和增加子节点

  如果要在一个Element下新一个子节点,我们采用Element.append(childElement)的方式。

path = root.find('path')
path.findall('object')
[]
obj = root.find('object')
path.append(obj)
path.findall('object')
[<Element 'object' at 0x7fd9adcec110>]

   可以看到在path下本来是没有object这个子节点的,但是在append之后就有了(要注意的是我们append只有是Element对象)

  删除一个子节点采用的是Element.remove(childElement)的方式。

path.remove(obj)
path.findall('object')
[]

  也要注意的是参数只能是Element对象并且还得是同一个内存。 

obj = root.findall('object')[1]
path.remove(obj)
ValueError: list.remove(x): x not in list

  如果我们删除的是另一个obj对象(这里会报错的),原因是path的子节点的并不是我们新创建的这个obj。

三、保存xml文件

   对于我们已经修改完成的xml,以上改了属性,增加了子节点,删除了字节点,把操作后的tree保存成新的xml文件。采用 

import xml.etree.ElementTree as ET
file_xml = '/home/g4/桌面/project/安全帽100/99.xml'
tree = ET.parse(file_xml)   # 读取tree
root = tree.getroot()
path = root.find('path')
obj = root.find('object')
path.append(obj)            # 在path子节点下增加一个子节点
root.remove(obj)            # 在root节点下删除一个子节点

new_tree = ET.ElementTree(root) # root为修改后的root new_tree.write("test.xml", encoding='utf-8')  # 保存为xml文件

  最主要的保存操作是最后两行,这里由于存在中文,因此传入参数encoding=‘utf-8’。

  看看最后结果。

 

 

 

参考链接:

https://blog.csdn.net/weixin_42782150/article/details/106219001

posted @ 2021-08-25 16:40  Circle_Wang  阅读(8975)  评论(0编辑  收藏  举报