5月28日 03:47
XML 解析中 DOM 和 SAX 有什么区别?
DOM 把整个 XML 一次性加载到内存建树,SAX 逐行读、遇到标签就触发回调。所以 DOM 能随机访问、能改,但吃内存;SAX 省内存、速度快,但只能顺序读、不能改。面试里一般答到"一个树一个事件驱动"就算到位,但追问肯定会问更细。
追问
DOM 和 SAX 的内存差距到底有多大?
解析一个 100MB 的 XML,DOM 可能吃掉 300-500MB 内存(树节点的对象开销远大于原始文本),SAX 基本只占几 KB 的缓冲区。大文件用 DOM 直接 OOM 是真实生产事故,不是理论风险。
StAX 和 SAX 有什么区别?为什么有了 SAX 还要 StAX?
SAX 是推模型——解析器主动推事件给你,你没法控制解析节奏。StAX 是拉模型——你调用 next() 主动拉下一个事件,想停就停,想跳就跳。实际开发中 StAX 更灵活,代码也更好写(不用写一堆回调)。JDK 6 开始 StAX 就是 JAXP 的一部分了。
实际项目里怎么选?
| 场景 | 选择 | 原因 |
|---|---|---|
| 配置文件(几十 KB) | DOM / Dom4j | 小文件内存不是问题,随机访问方便 |
| 大日志文件(几百 MB+) | SAX / StAX | 流式处理不爆内存 |
| 需要修改 XML 再写回 | DOM | SAX 只读,改不了 |
| 只提取少数字段 | SAX / StAX | 不用为几个字段加载整棵树 |
JAXB 还在用吗?
Java 9 标记废弃,Java 11 正式移除(从 JDK 里删了)。现在要用得手动加 jakarta.xml.bind 依赖。新项目如果要做 XML-对象映射,Jackson 的 XML 模块比 JAXB 好用。
DOM 解析有什么常见坑?
- 编码问题:XML 声明的 encoding 和文件实际编码不一致,直接乱码或抛异常
- 空白节点:格式化缩进会产生大量
#text空白节点,遍历时要getNodeType()过滤,否则逻辑全乱 - 命名空间:带命名空间的 XML 必须用
getElementsByTagNameNS(),用错方法查不到元素 - 实体注入:外部实体引用(XXE)是安全漏洞,解析时必须禁用:
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)
写段代码
StAX 拉式解析,对比上面 SAX 的回调写法,感受下代码简洁度的差距:
javaXMLStreamReader reader = XMLInputFactory.newInstance() .createXMLStreamReader(new FileInputStream("data.xml")); while (reader.hasNext()) { if (reader.next() == START_ELEMENT && reader.getLocalName().equals("title")) { System.out.println(reader.getElementText()); } }