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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM