首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

Python解析XML利器—xml.etree.ElementTree

  • 23-11-14 09:53
  • 3473
  • 12077
blog.csdn.net

Python解析XML利器—xml.etree.ElementTree

文章目录

  • Python解析XML利器—xml.etree.ElementTree
    • 前言
      • 1、ElementTree的xml形态
      • 2、单个Element的xml形态
    • 一、Element常用属性和XML对应
      • 1、tag
      • 2、attrib
      • 3、text
      • 4、child elements
    • 二、ElementTree
      • 1、Python的ElementTree解析:
      • 2、Element之查找
    • 三、Element修改
      • 1、修改方法
      • 2、修改示例
      • 3、删除示例
    • 四、后记

前言

xml格式作为netconf配置文件的格式,有一定的研究价值,但是xml作为一种标记语言,非常不利于**“network engineer”**识别。解析xml文件是一件很烦的事情。Python内置的API:xml.etree.ElementTree 可以解决这个问题。但是其语法和特性非常麻烦。详见官网文档:

xml.etree.ElementTree - The ElementTree XML API - Python 3.10.4 documentationdocs.python.org/3/library/xml.etree.elementtree.html

xml是一种固有的分层数据格式,最自然的表示方式是解析成树状。 ElementTree将整个 xml 文档解析成树状结构, Element就表示这个树状结构中的单节点。

整个xml文档与Python交互(读取和写入文件)是在ElementTree(相当于整棵树)上完成。单个 xml 元素及其子元素的交互是在Element(相当于leaf)上完成。

1、ElementTree的xml形态


<dev_info id="netmiko_inventory">
   <R1 type="cisco">
       <device_type>cisco_iosdevice_type>
       <username>adminusername>
       <password>ciscopassword>
       <ip>192.168.47.10ip>
   R1>
   <SW3 type="huawei">
       <device_type>huawei_vrpv8device_type>
       <username>adminusername>
       <password>huaweipassword>
       <ip>192.168.47.30ip>
   SW3>
dev_info>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

2、单个Element的xml形态

<device_type desc="platform">cisco_iosdevice_type>
  • 1

一、Element常用属性和XML对应

Element常用属性对应的xml格式

<tag attrib=“netmiko_inventory”>texttag>
  • 1

例:

<device_type desc="platform">cisco_iosdevice_type>
    tag       attrib         text       tag
  • 1
  • 2

1、tag

tag是str对象,表示xml标签,例子中的前后闭合的device_type

2、attrib

attrib是一个dict对象,表示xml属性,例子中的desc=“platform”

3、text

text就是xml数据标签包裹的内容,也是Element的内容,例子中的 cisco_ios

4、child elements

child elements则是xml一对标签中包含的子集,如下图,类似于R1和SW3标签中包裹的内容


<dev_info id="netmiko_inventory">
   <R1 type="cisco">
       <device_type>cisco_iosdevice_type>
       <username>adminusername>
       <password>ciscopassword>
       <ip>192.168.47.10ip>
   R1>
   <SW3 type="huawei">
       <device_type>huawei_vrpv8device_type>
       <username>adminusername>
       <password>huaweipassword>
       <ip>192.168.47.30ip>
   SW3>
dev_info>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

二、ElementTree

ElementTree可以把整个xml文件解析成树形结构。

xml文件:


<dev_info id="netmiko_inventory">
   <R1 type="cisco">
       <device_type>cisco_iosdevice_type>
       <username>adminusername>
       <password>ciscopassword>
       <ip>192.168.47.10ip>
   R1>
   <SW3 type="huawei">
       <device_type>huawei_vrpv8device_type>
       <username>adminusername>
       <password>huaweipassword>
       <ip>192.168.47.30ip>
   SW3>
dev_info>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

1、Python的ElementTree解析:

使用ElementTree能快速的把xml文件解析成ElementTree

from xml.etree import ElementTree as ET

# 直接读取xml文件,形成ElementTree结构
tree = ET.parse('lab1.xml')
root = tree.getroot() # 获取root tag

print(root.tag) # 打印root的tag
print(root.attrib) # 打印root的attrib
# 使用root索引访问标签的值,[0]是R1标签,[0]是R1标签中的第一个标签device_type, .text是取这个标签的值,自然值就是cisco_ios
print(root[0][0].text)
print('
')

for child in root: # 打印root的child层的tag和attrib
   print(child.tag, child.attrib)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

解析结果

username@usernamedeMacBookPro1 xmlLab %python -u"/Users/username/Coding/Test/xmlLab/xml_lab1.py"
dev_info # 注意,标签tag的数据结构是str
{'id': 'netmiko_inventory'} # 注意,属性attrib的数据结构是dict
cisco_ios

R1 {'type': 'cisco'} # 由此可见,遍历出来的tag是str,attrib是dict
SW3 {'type': 'huawei'}
username@usernamedeMacBookPro1 xmlLab %
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2、Element之查找

Element有很丰富的查找方法,总结如下:

iter(tag=None) 遍历Element的child,可以指定tag精确查找
findall(match) 查找当前元素tag或path能匹配的child节点
find(match) 查找当前元素tag或path能匹配的第一个child节点
get(key, default=None) 获取元素指定key对应的attrib,如果没有attrib,返回default。
  • 1
  • 2
  • 3
  • 4

(1)iter

Element使用iter迭代器可以递归地遍历它下面的所有child

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse('lab1.xml')
>>> root = tree.getroot()
>>> 
>>> for dev in root.iter('username'):
...     print(dev.tag)
... 
username
username
>>> 
>>> for dev in root.iter('username'):
...     print(dev.text)
... 
admin
admin
>>> 
>>> for dev in root.iter('password'):
...     print(dev.text)
... 
cisco
huawei
>>> 
>>> for dev in root.iter('R1'):
...     print(dev.attrib)
... 
{'type': 'cisco'}
>>> 
>>> for dev in root.iter('SW3'):
...     print(dev.attrib)
... 
{'type': 'huawei'}
>>>  
>>> for dev in root.iter():
...     print(dev.attrib)
... 
{'id': 'netmiko_inventory'}
{'type': 'cisco'}
{}
{}
{}
{}
{'type': 'huawei'}
{}
{}
{}
{}
>>> for dev in root.iter():
...     print(dev.tag)
... 
dev_info
R1
device_type
username
password
ip
SW3
device_type
username
password
ip
>>> 
>>> for dev in root.iter():
...     print(dev.text)
... 

   

       
cisco_ios
admin
cisco
192.168.47.10

       
huawei_vrpv8
admin
huawei
192.168.47.30
>>>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

(2)findall、find

Element使用finall可以查找当前元素tag或path能匹配的child节点

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse('lab1.xml')
>>> root = tree.getroot()
>>>
>>> for user_passwd in root.findall('R1'):
...     cisco_user = user_passwd.find('username').text
...     cisco_passwd = user_passwd.find('password').text
...     print(f'cisco user: {cisco_user} password: {cisco_passwd}')
... 
cisco user: admin password: cisco
>>>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

ElementTree的查找非常方便,可以加以利用,个人强烈不建议使用ElementTree去修改xml文件

三、Element修改

ElementTree可以使用很多方法来修改xml文件,确认修改完毕后,可以使用ElementTree.write()方法写入

不建议网工使用该功能

1、修改方法

Element.text 直接修改字段
Element.remove() 删除字段
Element.set() 添加或修改属性attrib
with Element.append() 添加新的child
  • 1
  • 2
  • 3
  • 4

2、修改示例

把R1的ip地址由192.168.47.10修改成192.168.47.1

修改前的xml文件


<dev_info id="netmiko_inventory">
   <R1 type="cisco">
       <device_type>cisco_iosdevice_type>
       <username>adminusername>
       <password>ciscopassword>
       <ip>192.168.47.10ip>
   R1>
   <SW3 type="huawei">
       <device_type>huawei_vrpv8device_type>
       <username>adminusername>
       <password>huaweipassword>
       <ip>192.168.47.30ip>
   SW3>
dev_info>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

修改代码

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse('lab1.xml')
>>> root = tree.getroot()
>>>
>>> for dev in root.iter('R1'):
...     dev.find('ip').text = str('192.168.47.1')
... 
>>> tree.write('./lab1.xml')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

修改后的xml:

<dev_info id="netmiko_inventory">
   <R1 type="cisco">
       <device_type>cisco_iosdevice_type>
       <username>adminusername>
       <password>ciscopassword>
       <ip>192.168.47.1ip> # 注意看修改后的地址
   R1>
   <SW3 type="huawei">
       <device_type>huawei_vrpv8device_type>
       <username>adminusername>
       <password>huaweipassword>
       <ip>192.168.47.30ip>
   SW3>
dev_info>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

3、删除示例

删除SW3的标签部分

<dev_info id="netmiko_inventory">
   <R1 type="cisco">
       <device_type>cisco_iosdevice_type>
       <username>adminusername>
       <password>ciscopassword>
       <ip>192.168.47.1ip>
   R1>
   <SW3 type="huawei">
       <device_type>huawei_vrpv8device_type>
       <username>adminusername>
       <password>huaweipassword>
       <ip>192.168.47.30ip>
   SW3>
dev_info>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

修改代码

>>> for dev in root.findall('SW3'):
...     root.remove(dev)
... 
>>> tree.write('./lab1.xml')
  • 1
  • 2
  • 3
  • 4

修改后的xml:

<dev_info id="netmiko_inventory">
   <R1 type="cisco">
       <device_type>cisco_iosdevice_type>
       <username>adminusername>
       <password>ciscopassword>
       <ip>192.168.47.1ip>
   R1>
dev_info>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

四、后记

xml.etree.ElementTree提供的解析方法,适合网络工程师用来解析、查找xml元素,但其复杂的特性制约了修改和构建,因为网工毕竟不是“专业代码玩家”使用起来非常容易出错。个人不推荐使用它来修改、构建xml文件。

《AUTOSAR谱系分解(ETAS工具链)》之总目录

注:本文转载自blog.csdn.net的PlutoZuo的文章"https://blog.csdn.net/PlutoZuo/article/details/133824969"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top