本文目录导读:

- ElementTree(标准库)- 推荐使用
- lxml(第三方库)- 功能更强大
- minidom(标准库)- 基础但更直观
- cElementTree(标准库)- 高性能版本
- 实践示例:完整XML处理
- 性能对比和建议
- 选择建议
我来介绍几种在Python中解析XML数据的主要方法:
ElementTree(标准库)- 推荐使用
解析XML文件
import xml.etree.ElementTree as ET
# 解析XML字符串
xml_string = '''
<books>
<book id="1">
<title>Python编程</title>
<author>张三</author>
<price>59.9</price>
</book>
<book id="2">
<title>数据结构</title>
<author>李四</author>
<price>45.0</price>
</book>
</books>
'''
# 解析字符串
root = ET.fromstring(xml_string)
# 解析文件
# tree = ET.parse('books.xml')
# root = tree.getroot()
# 遍历所有book
for book in root.findall('book'):= book.find('title').text
author = book.find('author').text
price = book.find('price').text
book_id = book.get('id')
print(f"ID:{book_id}, 书名:{title}, 作者:{author}, 价格:{price}")
常用操作方法
# 获取根标签名
print(f"根标签: {root.tag}")
# 获取属性
for book in root.findall('book'):
print(f"Book ID: {book.get('id')}")
# 查找特定元素
python_book = root.find(".//book[title='Python编程']")
if python_book is not None:
print(f"找到: {python_book.find('title').text}")
# 直接访问子元素
for book in root:
print(book.find('title').text)
lxml(第三方库)- 功能更强大
from lxml import etree
# 解析XML
xml_string = '''
<books>
<book category="programming">
<title lang="en">Learning Python</title>
<author>Mark Lutz</author>
<year>2013</year>
</book>
<book category="data">
<title lang="en">Data Science</title>
<author>Jake VanderPlas</author>
<year>2016</year>
</book>
</books>
'''
root = etree.fromstring(xml_string)
# 支持XPath查询s = root.xpath('//title/text()')
print(f"所有书名: {titles}")
# 条件查询
programming_books = root.xpath("//book[@category='programming']/title/text()")
print(f"编程类书籍: {programming_books}")
# 创建新XML
new_book = etree.SubElement(root, "book")
new_book.set("category", "python")elem = etree.SubElement(new_book, "title")elem.text = "Python基础教程"
print(etree.tostring(root, pretty_print=True, encoding='unicode'))
minidom(标准库)- 基础但更直观
from xml.dom import minidom
# 解析XML
xml_string = '''
<students>
<student id="001">
<name>小明</name>
<age>20</age>
<grade>A</grade>
</student>
<student id="002">
<name>小红</name>
<age>21</age>
<grade>B</grade>
</student>
</students>
'''
dom = minidom.parseString(xml_string)
# 获取根元素
root = dom.documentElement
# 获取所有student元素
students = root.getElementsByTagName('student')
for student in students:
name = student.getElementsByTagName('name')[0].firstChild.data
age = student.getElementsByTagName('age')[0].firstChild.data
grade = student.getElementsByTagName('grade')[0].firstChild.data
student_id = student.getAttribute('id')
print(f"ID:{student_id}, 姓名:{name}, 年龄:{age}, 等级:{grade}")
cElementTree(标准库)- 高性能版本
# Python 3.3+直接使用ElementTree,它会自动使用C实现
import xml.etree.ElementTree as ET
# 如果需要明确使用C实现(Python 3.3以下版本)
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
# 后续使用相同
实践示例:完整XML处理
import xml.etree.ElementTree as ET
import json
class XMLProcessor:
def __init__(self, xml_string=None, file_path=None):
if xml_string:
self.root = ET.fromstring(xml_string)
elif file_path:
tree = ET.parse(file_path)
self.root = tree.getroot()
else:
self.root = None
def to_dict(self, element=None):
"""将XML转换为字典"""
if element is None:
element = self.root
result = {}
# 处理属性
if element.attrib:
result['@attributes'] = element.attrib
# 处理子元素
children = list(element)
if children:
child_dict = {}
for child in children:
child_data = self.to_dict(child)
tag = child.tag
# 处理重复标签
if tag in child_dict:
if not isinstance(child_dict[tag], list):
child_dict[tag] = [child_dict[tag]]
child_dict[tag].append(child_data)
else:
child_dict[tag] = child_data
result.update(child_dict)
# 处理文本内容
text = element.text and element.text.strip()
if text and not result:
result = text
elif text:
result['#text'] = text
return result
def find_all(self, tag_name):
"""查找所有指定标签的元素"""
return self.root.findall(f'.//{tag_name}')
def find_by_attribute(self, tag_name, attr_name, attr_value):
"""根据属性查找元素"""
xpath = f".//{tag_name}[@{attr_name}='{attr_value}']"
return self.root.find(xpath)
# 使用示例
xml_data = '''
<config>
<database>
<host>localhost</host>
<port>3306</port>
<name>testdb</name>
</database>
<app>
<name>MyApp</name>
<version>1.0.0</version>
<settings>
<setting key="debug">true</setting>
<setting key="max_users">100</setting>
</settings>
</app>
</config>
'''
processor = XMLProcessor(xml_string=xml_data)
# 转换为字典
config_dict = processor.to_dict()
print(json.dumps(config_dict, indent=2, ensure_ascii=False))
# 查找特定元素
host_elem = processor.find_all('host')
print(f"数据库主机: {host_elem[0].text if host_elem else '未找到'}")
debug_setting = processor.find_by_attribute('setting', 'key', 'debug')
if debug_setting is not None:
print(f"Debug模式: {debug_setting.text}")
性能对比和建议
# 性能基准测试
import time
import xml.etree.ElementTree as ET
from lxml import etree
# 生成测试数据
test_xml = '<root>' + ''.join([f'<item id="{i}"><name>Item{i}</name></item>' for i in range(10000)]) + '</root>'
# ElementTree
start = time.time()
root = ET.fromstring(test_xml)
items = root.findall('item')
et_time = time.time() - start
# lxml
start = time.time()
root = etree.fromstring(test_xml)
items = root.xpath('//item')
lxml_time = time.time() - start
print(f"ElementTree: {et_time:.4f}s")
print(f"lxml: {lxml_time:.4f}s")
选择建议
| 方法 | 适用场景 | 性能 | 功能 |
|---|---|---|---|
| ElementTree | 通用场景,标准库 | 中等 | 基础功能 |
| lxml | 复杂查询,大数据 | 高 | 最强大 |
| minidom | 简单操作,兼容性 | 低 | 基础功能 |
| cElementTree | Python 2.x | 高 | 同ElementTree |
推荐:日常使用 ElementTree(标准库,无需安装),复杂场景使用 lxml。