Python 提供了多种处理 XML 的方式,三种方法解析 XML:ElementTree、SAX 以及 DOM。
1. ElementTree
xml.etree.ElementTree 是 Python 标准库中用于处理 XML 的模块,它提供了简单而高效的 API,用于解析和生成 XML 文档。
2.SAX (simple API for XML )
Python 标准库包含 SAX 解析器,SAX 用事件驱动模型,通过在解析 XML 的过程中触发一个个的事件并调用用户定义的回调函数来处理 XML 文件。
3.DOM(Document Object Model)
将 XML 数据在内存中解析成一个树,通过对树的操作来操作 XML。
目录
1. xml.etree.ElementTree (推荐)
ElementTree 是 Python 标准库中最常用的 XML 处理模块,它提供了轻量级且高效的 API。
1.1 基本用法
import xml.etree.ElementTree as ET
# 解析 XML 文件
tree = ET.parse('example.xml')
root = tree.getroot()
# 或者直接解析字符串
xml_string = '<root><child>Content</child></root>'
root = ET.fromstring(xml_string)
1.2 遍历 XML 树
# 遍历所有子节点
for child in root:
print(child.tag, child.attrib)
# 递归遍历所有元素
for elem in root.iter():
print(elem.tag, elem.text)
# 查找特定标签
for neighbor in root.iter('neighbor'):
print(neighbor.attrib)
1.3 访问元素数据
# 访问元素属性
print(root[0].attrib['name'])
# 访问元素文本内容
print(root[0].text)
# 使用 find 方法
country = root.find("country")
rank = country.find('rank').text
1.4 修改 XML
# 修改元素文本
root[0][0].text = "New Rank"
# 修改元素属性
root[0].attrib['name'] = 'Updated Name'
# 添加新元素
new_elem = ET.SubElement(root, 'newchild')
new_elem.text = "New Content"
# 删除元素
root.remove(root[0])
# 保存修改
tree.write('updated.xml')
1.5 命名空间处理
# 注册命名空间
ET.register_namespace('', "http://example.com/ns")
# 带命名空间的查找
namespaces = {'ns': 'http://example.com/ns'}
for elem in root.findall('ns:child', namespaces):
print(elem.text)
2. xml.dom.minidom
minidom 提供了 DOM (Document Object Model) 方式的 XML 解析,适合需要完整 DOM 功能的场景。
2.1 基本用法
from xml.dom import minidom
# 解析 XML
doc = minidom.parse('example.xml')
# 获取根元素
root = doc.documentElement
# 获取元素列表
items = root.getElementsByTagName('item')
2.2 访问数据
# 获取第一个 item
first_item = items[0]
# 获取属性
print(first_item.getAttribute('id'))
# 获取文本内容
print(first_item.firstChild.data)
3. xml.sax
SAX (Simple API for XML) 是基于事件驱动的解析方式,适合处理大型 XML 文件。
3.1 基本用法
import xml.sax
class MyHandler(xml.sax.ContentHandler):
def startElement(self, name, attrs):
print(f"开始元素: {name}")
def endElement(self, name):
print(f"结束元素: {name}")
def characters(self, content):
print(f"内容: {content.strip()}")
# 创建解析器
parser = xml.sax.make_parser()
parser.setContentHandler(MyHandler())
# 解析 XML
parser.parse('example.xml')
4. lxml (第三方库)
lxml 是一个功能强大的第三方库,兼容 ElementTree API 但提供了更多功能。
4.1 安装
pip install lxml
4.2 基本用法
from lxml import etree
# 解析 XML
tree = etree.parse('example.xml')
root = tree.getroot()
# XPath 查询
results = root.xpath('//country[@name="Singapore"]')
for r in results:
print(etree.tostring(r))
5. XML 解析方法对比
| 方法/特性 | ElementTree | minidom | SAX | lxml |
|---|---|---|---|---|
| 内存使用 | 中等 | 高 | 低 | 中等 |
| 速度 | 快 | 慢 | 最快 | 非常快 |
| API 易用性 | 简单 | 复杂 | 复杂 | 简单 |
| 支持 XPath | 有限 | 无 | 无 | 完全支持 |
| 适合文件大小 | 中小型 | 小型 | 大型 | 各种大小 |
6. 实际应用示例
6.1 解析 RSS 订阅
import xml.etree.ElementTree as ET
import urllib.request
# 下载并解析 RSS
url = 'https://example.com/feed.rss'
with urllib.request.urlopen(url) as response:
tree = ET.parse(response)
root = tree.getroot()
# 提取新闻条目
for item in root.findall('.//item'):
title = item.find('title').text
link = item.find('link').text
print(f"{title}\n{link}\n")
6.2 生成 XML 文件
python
复制
下载
import xml.etree.ElementTree as ET
# 创建根元素
root = ET.Element('catalog')
# 添加子元素
for i in range(1, 4):
book = ET.SubElement(root, 'book', id=str(i))
title = ET.SubElement(book, 'title')
title.text = f"Book {i}"
author = ET.SubElement(book, 'author')
author.text = f"Author {i}"
# 创建 ElementTree 对象并保存
tree = ET.ElementTree(root)
tree.write('books.xml', encoding='utf-8', xml_declaration=True)
6.3 转换 XML 为字典
def xml_to_dict(element):
result = {}
for child in element:
if len(child) == 0:
result[child.tag] = child.text
else:
result[child.tag] = xml_to_dict(child)
return result
root = ET.parse('data.xml').getroot()
data_dict = xml_to_dict(root)
print(data_dict)
7. 安全注意事项
-
XML 炸弹:防范类似 "billion laughs" 的攻击
parser = ET.XMLParser(resolve_entities=False) # 禁用实体解析 -
敏感数据:XML 可能包含敏感信息,解析时注意保护
-
输入验证:始终验证输入的 XML 数据
对于大多数应用场景,xml.etree.ElementTree 是最佳选择,它平衡了性能和易用性。对于需要高性能或高级功能(如完整 XPath 支持)的场景,可以考虑使用 lxml。
1466

被折叠的 条评论
为什么被折叠?



