Python的xml.sax模块是基于事件驱动的XML解析工具,适用于大文件或内存受限场景;需继承ContentHandler类并重写startElement、characters、endElement等方法来处理标签和文本事件。

Python 的 xml.sax 模块是标准库中用于事件驱动(SAX)XML 解析的工具,适合处理大文件、内存受限或只需提取部分数据的场景。它不加载整个文档到内存,而是边读边触发回调,由你定义的处理器响应事件。
核心思路:写一个 ContentHandler 子类
SAX 解析的关键是实现 xml.sax.handler.ContentHandler 的子类,重写其中的方法来捕获开始标签、结束标签、文本内容等事件。系统会在解析过程中自动调用这些方法。
-
startElement(name, attrs):遇到开始标签时调用,
name是标签名,attrs是xml.sax.xmlreader.AttributesImpl对象,可用attrs.get('attr_name')或dict(attrs)获取属性 - characters(content):遇到标签内文本时调用,注意可能被多次调用(比如含换行或CDATA),需累积拼接
- endElement(name):遇到结束标签时调用,可在此做收尾操作(如保存当前对象、清空临时变量)
基本使用步骤
三步走:准备处理器 → 创建解析器 → 解析文件或流
- 定义自己的
ContentHandler子类(比如叫BookHandler) - 用
xml.sax.make_parser()创建解析器实例 - 调用
parser.setContentHandler(your_handler)设置处理器 - 调用
parser.parse('file.xml')或parser.parse(io.StringIO(xml_str))
一个小而完整的例子
假设 XML 是这样:
立即学习“Python免费学习笔记(深入)”;
对应处理器可以这样写:
import xml.saxclass BookHandler(xml.sax.ContentHandler): def init(self): self.books = [] self.current_tag = "" self.current_book = {} self.buffer = ""
def startElement(self, name, attrs): self.current_tag = name if name == "book": self.current_book = {"id": attrs.get("id", "")} def characters(self, content): if self.current_tag in ("title", "author"): self.buffer += content.strip() def endElement(self, name): if name == "title": self.current_book["title"] = self.buffer elif name == "author": self.current_book["author"] = self.buffer elif name == "book": self.books.append(self.current_book) self.buffer = "" self.current_tag = ""使用
handler = BookHandler() parser = xml.sax.make_parser() parser.setContentHandler(handler) parser.parse("books.xml") print(handler.books) # [{'id': '101', 'title': 'Python Cookbook', 'author': 'David Beazley'}]
注意事项和常见坑
SAX 是流式解析,没有 DOM 那样的树结构,也不支持 XPath 或回溯。几个实用提醒:
- 文本内容(
characters)可能被拆成多次调用,别直接覆盖,要累积 - 标签嵌套靠你自己用栈或状态变量管理(比如用
self.depth或列表记录当前路径) - 如果 XML 有命名空间,需继承
xml.sax.handler.ContentHandler并重写startElementNS等方法 - 报错时默认会抛异常,可通过
parser.setErrorHandler()自定义错误处理
基本上就这些。SAX 不复杂但容易忽略字符分段和状态维护,写清楚逻辑就能稳定工作。











