Python读取、修改、保存xml⽂件
  在做⽬标检测的时候,我们获取到图⽚的xml⽂件,我们想利⽤xml⽂件来解析得到我们想要的信息。或者我们想要对xml⽂件做⼀些修改,下⾯我将利⽤Python中⾃带的xml包来完成这
⼀系列的操作(其实还有⼀个⽤于解析HTML的包lxml也可以解析xml⽂件,也⾮常好⽤的,具体使⽤⽅法可以参看这篇博客)。参考⽹站我放在的底部,⾥⾯讲得也很详细。本⽂利⽤来演⽰
的xml模板结构如下图:
⼀、读取并解析xml⽂件
  我们主要使⽤的模块是ElementTree
 1、解析xml——获取xml树 
ElementTree as ET
file_xml = '/home/g4/桌⾯/project/l'  # xml⽂件路径
tree = ET.parse(file_xml)
type(tree)
  这⾥的tree的对象是ElementTree,从名字也可以知道这个数据结构类似于多叉树,我们可以通过dir()来查看这个类的属性和⽅法。
dir(tree)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__
  我们这⾥可以看到⾥⾯有find⽅法,findall⽅法,之后会讲到,使⽤⽅式。
  我们接下来要获取其根节点,以及其他节点的内容。
 2、解析xml——获取⼦节点及其节点内容
  获得⼀棵树之后我们,我们通过tree的getroot()⽅法来获得整颗树的根结点
root = t()
type(root)
dir(root)
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__  我们可以看到根结点的数据类型是Element,其实这棵树的所有节点数据类型都是Element,下⾯介绍这些⽅法和属性
1. root.find('xxx'):返回的是⼀个Element对象,也就是在该节点下提取出叫做‘xxx’这个字节点(如果有多个叫做xxx的⼦节点,将会返回⾸个)
2. root.findall('xxx'):返回值是⼀个列表,列表的每个元素是Element,也就是返回该节点下叫做‘xxx’的所有⼦节点,⽤list来储存
3. root.attrib :返回该Element所有的“属性”,是⼀个字典,该节点的“属性”就是<⾥⾯id,name这些东西>,⼀会可以结合⽰例xml⽂件,看到具体的返回值。
4. :返回⼀个字符串,是这个根节点的所包含的内容(也就是<obj>xxxx<obj>中的xxxx)
  接下来我们就根据着⽂章开头的⽰例xml,来展⽰⼀下以上介绍到的⽅法和属性
path = root.find('path')  # 获取root节点(annotation)下的叫做path的这个节点
type(path)
root.attrib  # 获取annotation节点的属性(包含有两个属性⼀个是name,⼀个是id)
{'name': 'Panama', 'id': '1234'}
<   # 获取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、修改节点内容
  如果要修改节点的内容我们可以直接使⽤ = 'xxxx',就就可以完成修改了。
< = '修改后'
path = root.find('path')
<
'修改后'
  上⾯的例⼦显⽰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对象)  删除⼀个⼦节点采⽤的是ve(childElement)的⽅式。
path.findall('object')
[]
  也要注意的是参数只能是Element对象并且还得是同⼀个内存。
python处理xml文件obj = root.findall('object')[1]
ValueError: ve(x): x not in list
  如果我们删除的是另⼀个obj对象(这⾥会报错的),原因是path的⼦节点的并不是我们新创建的这个obj。
三、保存xml⽂件
  对于我们已经修改完成的xml,以上改了属性,增加了⼦节点,删除了字节点,把操作后的tree保存成新的xml⽂件。采⽤ElementTree as ET
file_xml = '/home/g4/桌⾯/project/安全帽l'
tree = ET.parse(file_xml)  # 读取tree
root = t()
path = root.find('path')
obj = root.find('object')
path.append(obj)            # 在path⼦节点下增加⼀个⼦节点
new_tree = ET.ElementTree(root)  # root为修改后的root
new_tree.write("l", encoding='utf-8')  # 保存为xml⽂件
  最主要的保存操作是最后两⾏,这⾥由于存在中⽂,因此传⼊参数encoding=‘utf-8’。
  看看最后结果。
参考链接:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。