xml.etree.ElementTree(简称ElementTree)是Python标准库中用于处理XML文件的模块。它提供了简洁且高效的API,适用于解析、创建和修改XML文档。在需要处理XML数据的场景中,比如配置文件、数据交换格式、Web服务响应等,ElementTree都是非常实用的工具。
解析字符串形式的XML:
1 2 3 4 5 6 7 8 9 10 11 |
import xml.etree.ElementTree as ET
xml_data = '''<data> <user> <name>John</name> <age>30</age> </user> </data>'''
root = ET.fromstring(xml_data) print(root.tag) |
输出:
data
解析XML文件:
1 2 3 4 5 |
import xml.etree.ElementTree as ET
tree = ET.parse('example.xml') root = tree.getroot() print(root.tag) |
输出:
data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import xml.etree.ElementTree as ET
# 创建根元素 root = ET.Element('data')
# 创建子元素 user = ET.SubElement(root, 'user') name = ET.SubElement(user, 'name') name.text = 'John' age = ET.SubElement(user, 'age') age.text = '30'
# 将XML树写入文件 tree = ET.ElementTree(root) tree.write('output.xml', encoding='utf-8', xml_declaration=True) |
生成的output.xml内容:
1 2 3 4 5 6 7 |
<?xml version='1.0' encoding='utf-8'?> <data> <user> <name>John</name> <age>30</age> </user> </data> |
修改现有元素的文本内容:
1 2 3 4 5 6 7 8 9 |
import xml.etree.ElementTree as ET
tree = ET.parse('output.xml') root = tree.getroot()
# 修改元素内容 root.find('user/name').text = 'Jane'
tree.write('output_modified.xml', encoding='utf-8', xml_declaration=True) |
output_modified.xml内容:
1 2 3 4 5 6 7 |
<?xml version='1.0' encoding='utf-8'?> <data> <user> <name>Jane</name> <age>30</age> </user> </data> |
遍历所有子元素:
1 2 3 4 5 6 7 |
import xml.etree.ElementTree as ET
tree = ET.parse('output.xml') root = tree.getroot()
for child in root.iter(): print(child.tag, child.text) |
输出:
data None
user None
name John
age 30
查找特定元素:
1 2 3 4 5 6 7 |
import xml.etree.ElementTree as ET
tree = ET.parse('output.xml') root = tree.getroot()
name = root.find('user/name') print(name.text) |
输出:
John
命名空间在复杂XML文档中非常常见,用于区分不同元素的作用域。
解析带有命名空间的XML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import xml.etree.ElementTree as ET
xml_data = '''<root xmlns:h="http://www.w3.org/TR/html4/" xmlns:f="http://www.w3schools.com/furniture"> <h:table> <h:tr> <h:td>Apples</h:td> <h:td>Bananas</h:td> </h:tr> </h:table> <f:table> <f:name>African Coffee Table</f:name> <f:width>80</f:width> <f:length>120</f:length> </f:table> </root>'''
root = ET.fromstring(xml_data)
# 使用命名空间解析 for table in root.findall('{http://www.w3.org/TR/html4/}table'): for td in table.findall('{http://www.w3.org/TR/html4/}td'): print(td.text) |
输出:
Apples
Bananas
虽然ElementTree本身不支持完整的XPath语法,但提供了类似的路径查找功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import xml.etree.ElementTree as ET
xml_data = '''<root> <users> <user id="1"> <name>John</name> </user> <user id="2"> <name>Jane</name> </user> </users> </root>'''
root = ET.fromstring(xml_data)
# 查找id为2的用户的名称 name = root.find('.//user[@id="2"]/name').text print(name) |
输出:
Jane
当需要处理大量的XML数据时,可以利用生成器或者批量处理方法来提高效率。
1 2 3 4 5 6 7 8 9 10 11 |
import xml.etree.ElementTree as ET
def parse_large_xml(file): context = ET.iterparse(file, events=('start', 'end')) for event, elem in context: if event == 'end' and elem.tag == 'user': yield elem elem.clear() # 清除元素以节省内存
for user in parse_large_xml('large_users.xml'): print(user.find('name').text) |
如上所述,使用iterparse()和生成器可以有效节省内存并提高处理速度,适用于大文件的解析。
默认情况下,ElementTree生成的XML是无缩进的,可以通过手动调整生成XML的格式来使其更具可读性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import xml.etree.ElementTree as ET
def indent(elem, level=0): i = "\n" + level*" " if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + " " if not elem.tail or not elem.tail.strip(): elem.tail = i for subelem in elem: indent(subelem, 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") child = ET.SubElement(root, "child") indent(root) tree = ET.ElementTree(root) tree.write("output_pretty.xml", encoding="utf-8", xml_declaration=True) |
生成的output_pretty.xml内容:
1 2 3 4 |
<?xml version='1.0' encoding='utf-8'?> <root> <child /> </root> |
在处理来自不受信任源的XML数据时,最好禁用外部实体,以防止XML外部实体注入(XXE)攻击。
1 2 3 4 5 6 7 8 9 |
import xml.etree.ElementTree as ET from defusedxml.ElementTree import parse, fromstring
# 安全地解析XML tree = parse('example.xml') root = tree.getroot()
# 或者 root = fromstring(xml_data) |
defusedxml库提供了更安全的XML解析方法,防止常见的安全漏洞。