小数据选 dom,因可随机访问和修改;大数据选 sax,因流式解析内存占用低。
XML 解析选 DOM 还是 SAX?看数据规模和修改需求
小数据(DOM;大数据流式处理、只读遍历或内存受限时,SAX 或 StAX 更稳。Python 的 xml.etree.ElementTree 默认是轻量 DOM 模型,够用但不支持 DTD 验证;Java 里 javax.xml.parsers.DocumentBuilder 构建的 DOM 会全量加载,容易 OOM。
- DOM 修改后需显式调用
write()或序列化才能持久化,不是“自动保存” - SAX 没有树结构,无法回溯父节点,回调中必须自己维护上下文栈
- Go 的
encoding/xml是类 SAX 的 Unmarshal 流程,但底层按字段名匹配,大小写敏感且依赖 struct tag,比如xml:"user_name"才能映射<user_name></user_name>
字段名不一致时,别硬改 XML,用映射配置或 tag 声明
XML 标签名常含下划线、驼峰混用或带命名空间前缀(如 <orderdate></orderdate>),直接映射到对象字段会失败。主流语言都支持声明式绑定:Python 的 dataclasses_xml 用 @attr 和 @element 注解;Java 的 JAXB 用 @XmlElement(name = "order_date");C# 的 XmlSerializer 支持 [XmlElement("order-date")]。
import dataclasses_xml as dx from dataclasses import dataclass <p>@dataclass class Order: order_id: int = dx.field(xml="orderId") # 映射 <orderId> created_at: str = dx.field(xml="created-at") # 映射 <created-at></p>
注意:不要在解析前用正则全局替换 XML 标签名——会破坏 CDATA、属性值、注释等合法内容。
空元素、缺失标签、文本混合子节点,这些才是真实 XML 的坑
规范 XML 可能写成 <price></price>、<price></price> 或干脆不出现该标签,但业务逻辑常要求统一为 0.0 或 None。ElementTree 默认把空标签当 text=None,而 lxml 的 etree.XMLParser(remove_blank_text=True) 可清理冗余空白,避免 text=" " 被误判为有效值。