基于DOM
导入: import xml.dom.minidom as minidom
写入
创建文档:dom = minidom.getDOMImplementation().createDocument(None,'Root',None)
获得根节点:root = dom.documentElement
创建节点:element = dom.createElement('Name')
给这个节点添加文本:element.appendChild(dom.createTextNode('default'))
注意:这里的节点文本值是存成另外一个节点的,是createTextNode
设置属性:element.setAttribute('age', '20')
添加到节点:root.appendChild(element)
完整代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23# -*- coding:utf-8 -*-
import xml.dom.minidom as minidom
dom = minidom.getDOMImplementation().createDocument(None,'Root',None)
root = dom.documentElement
for i in range(5):
element = dom.createElement('Name')
element.appendChild(dom.createTextNode('default'))
element.setAttribute('age', str(i))
root.appendChild(element)
# 保存文件
with open('default.xml', 'w', encoding='utf-8') as f:
dom.writexml(f, addindent='\t', newl='\n',encoding='utf-8')
# 文档内容
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Name age="0">default</Name>
<Name age="1">default</Name>
<Name age="2">default</Name>
<Name age="3">default</Name>
<Name age="4">default</Name>
</Root>
读取
读取文档:dom = minidom.parse('default.xml')
获得根节点:root = dom.documentElement
按照名称查找子节点,注意这里会递归查找所有子节点:names = root.getElementsByTagName('Name')
所有的子节点:root.childNodes
注意:每个节点的文本值存在TextNode
节点中,也就是最后一个节点的第一个子节点
查看是否含有属性:name.hasAttribute('age')
查看属性:name.getAttribute('age')
完整代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15dom = minidom.parse('default.xml')
root = dom.documentElement
names = root.getElementsByTagName('Name')
for name in names:
# 它的第一个子节点是一个textnode,存取的是真正的节点值
print(name.childNodes[0].nodeValue, end='\t')
if name.hasAttribute('age'):
print(name.getAttribute('age'), end='\t')
print('')
# 输出
default 0
default 1
default 2
default 3
default 4
基于ElementTree
导入:import xml.etree.ElementTree as ET
写入
创建节点:root = ET.Element('Root')
创建文档:tree = ET.ElementTree(root)
设置文本值:element.text = 'default'
设置属性:element.set('age', str(i))
添加节点:root.append(element)
写入文档:tree.write('default.xml', encoding='utf-8', xml_declaration=True)
但这样写入会有个问题,写入的XML
会在同一行,缺少换行符,Etree
本身并没有提供换行的选项,翻看了国外大神的回答,对root
处理以后,再次写入将有换行符。完整代码如下: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# -*- coding:utf-8 -*-
import xml.etree.ElementTree as ET
# 增加换行符
def __indent(elem, level=0):
i = "\n" + level*"\t"
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + "\t"
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
__indent(elem, level+1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
root = ET.Element('Root') # 创建节点
tree = ET.ElementTree(root) # 创建文档
for i in range(5):
element = ET.Element('Name')
element.set('age', str(i))
element.text = 'default'
root.append(element)
__indent(root) # 增加换行符
tree.write('default.xml', encoding='utf-8', xml_declaration=True)
# 文档内容
<?xml version='1.0' encoding='utf-8'?>
<Root>
<Name age="0">default</Name>
<Name age="1">default</Name>
<Name age="2">default</Name>
<Name age="3">default</Name>
<Name age="4">default</Name>
</Root>
读取
读取文档:tree = ET.parse('default.xml')
获得根节点:root = tree.getroot()
获得所有子节点:list(root)
查找子节点,注意这里不会递归查找所有子节点:root.findall('Name')
查找子节点,递归查找所有子节点:root.iter('Name')
查看节点名称:root.tag
全部代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23# -*- coding:utf-8 -*-
import xml.etree.ElementTree as ET
tree = ET.parse('default.xml')
root = tree.getroot()
for node in list(root):
print(node.text, node.tag, node.get('age'))
for node in root.findall('Name'):
print(node.text, node.tag, node.get('age'))
# 输出
default Name 0
default Name 1
default Name 2
default Name 3
default Name 4
default Name 0
default Name 1
default Name 2
default Name 3
default Name 4