xml(Extensible Markup Language,简称:XML)
可扩展标记语言,是一种netconf
配置文件的格式。是一种固有的分层数据格式,最自然的表示方式是解析成树状。 但是,xml
这样的标签数据,是面向“机器”识别的,是不利于“人类”识别的,所以看起来会比较的麻烦。
2003年5月成立了
Netconf
工作组,该工作组主要是为了提出一个全新的基于XML的网络配置(NETCONF
)协议而成立的。
Python
内置的API:xml.etree.ElementTree
可以解析xml
文件。ElementTree
将整个xml
文档解析成树状结构, Element
就表示这个树状结构中的单节点。
官方文件地址:The ElementTree XML API
后面举例以下面这个xml的文件形式展开,这也是官方给出的一个案例。xml
文档实例如下:
xml
文档实例如下:
<?xml version="1.0"?>
<data id="world country"><country name="Liechtenstein"><rank>1</rank><year>2008</year><gdppc>141100</gdppc><neighbor name="Austria" direction="E"/><neighbor name="Switzerland" direction="W"/></country><country name="Singapore"><rank>4</rank><year>2011</year><gdppc>59900</gdppc><neighbor name="Malaysia" direction="N"/></country><country name="Panama"><rank>68</rank><year>2011</year><gdppc>13600</gdppc><neighbor name="Costa Rica" direction="W"/><neighbor name="Colombia" direction="E"/></country>
</data>
一、xml 数据格式
Element
常用属性对应的xml
格式,如下:
<tag attrib=“netmiko_inventory”>text</tag>
例:
<device_type desc="platform">cisco_ios</device_type>tag attrib text tag
其中:
1、 tag
:是str对象,表示xml标签,例子中的前后闭合的device_type
2、 attrib
:是一个dict对象,表示xml属性,例子中的desc="platform"
3、 text
:是xml数据标签包裹的内容,也是Element
的内容,例子中的 cisco_ios
4、 child elements
:则是xml
一对标签中包含的子集,如下图,类似于country
标签中包裹的内容
举例:
import xml.etree.ElementTree as ET# 读取、解析文件,获取跟元素
tree = ET.parse('sample.xml')
root = tree.getroot()# 获取根元素的标签名称以及所有属性
# data
print('root.tag:', root.tag)
print('root.attrib:', root.attrib)# 获取text
print(root[0][1].text)
输出结果:
root.tag: data
root.attrib: {'id': 'world country'}
2008
二、查找方法
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
。
# 一次性获取所有名为 country 的元素、然后遍历
for country in root.findall('country'):# 获取 country 元素中的 name 属性name = country.get('name')# 寻找名为 rank 的子节点,获取其textrank = country.find('rank').text# 一次性获取所有名为 country 下 neighbor的元素、然后遍历neighbors = country.findall('neighbor')neighbor_name = []for neighbor in neighbors:n = neighbor.get('name')neighbor_name.append(n)print(name, rank, neighbor_name)
打印结果如下:
Liechtenstein 1 ['Austria', 'Switzerland']
Singapore 4 ['Malaysia']
Panama 68 ['Costa Rica', 'Colombia']
三、iter迭代器
Element使用iter迭代器可以递归地遍历它下面的所有child
# 一次性获取所有名为 country 的元素、然后遍历
for country in root.iter('country'):# 获取 country 元素中的 name 属性name = country.get('name')print(name)for rank in root.iter('rank'):# 获取 country 元素中的 name 属性rank_n = rank.textprint(rank_n)
打印结果如下:
Liechtenstein
Singapore
Panama1
4
68
四、xml数据转换成字典
xmltodict使用非常的简单,学习成本很低,可以快速的把xml格式的数据转换成字典,轻松进行数据二次加工。
代码如下:
import xmltodict, jsonwith open('sample.xml') as f:my_dict = xmltodict.parse(f.read())with open('info1.json', 'w') as f:json.dump(my_dict, f, sort_keys=False, indent=2)
打开info1.json
查看,保存的内容如下:
{"data": {"@id": "world country","country": [{"@name": "Liechtenstein","rank": "1","year": "2008","gdppc": "141100","neighbor": [{"@name": "Austria","@direction": "E"},{"@name": "Switzerland","@direction": "W"}]},{"@name": "Singapore","rank": "4","year": "2011","gdppc": "59900","neighbor": {"@name": "Malaysia","@direction": "N"}},{"@name": "Panama","rank": "68","year": "2011","gdppc": "13600","neighbor": [{"@name": "Costa Rica","@direction": "W"},{"@name": "Colombia","@direction": "E"}]}]}
}
其中:
tag
和attrib
都会变成字典的key
,例如,上面的data、id、country、name、rank
等等;- 但是,带有属性
attrib
的key
,会自动加入@
符号,其他不会; key
对应的value
,会变成字符串形式。
五、保存成xml
xmltodict
不仅可以将xml
转为字典形式,还可以将字典转成xml
形式,存储到本地,如下所示:
def saveXML():import xmltodictwith open('info.xml', 'w') as f:info_dict = {'dev_info': {'device_type': 'cisco_ios','username': 'admin','password': 'cisco','ip': '192.168.47.10'}}f.write(xmltodict.unparse(info_dict, pretty=True))
保存为xml文件后,打开查看结果如下:
<?xml version="1.0" encoding="utf-8"?>
<dev_info><device_type>cisco_ios</device_type><username>admin</username><password>cisco</password><ip>192.168.47.10</ip>
</dev_info>
六、总结
前面对xml
文件做了简单的学习,包括什么是xml
,以及在python
中怎么读取、操作和存储为xml
文件。同时将机器友好的xml
文件,转成对人友好的字典查看。xml
确实不太好查看和解析,弄起来有些费劲啊。