javax.xml.parsers包提供documentbuilderfactory和saxparserfactory工厂类;dom解析需设setnamespaceaware(true),用documentbuilder.parse()加载xml为内存树;sax解析需实现defaulthandler响应事件,适合大文件流式处理。

javax.xml.parsers 是 Java 标准库中用于创建 XML 解析器工厂的包,它本身不直接解析 XML,而是提供 DocumentBuilderFactory(DOM)和 SAXParserFactory(SAX)两类工厂类,用来生成具体的解析器实例。
如何用 DocumentBuilder 解析 XML 为 DOM 树
DOM 解析适合中小型 XML,解析后整个文档加载进内存,支持随机访问和修改。
- 必须调用
setNamespaceAware(true),否则带命名空间的 XML 会解析失败或节点名异常 - 默认不校验 DTD 或 XSD,如需验证,要设置
setValidating(true)并确保系统能访问外部 schema -
DocumentBuilder.parse()接收File、InputStream、InputSource等,但不能直接传字符串;若只有 XML 字符串,需包装成ByteArrayInputStream
String xml = "<root><item id='1'>A</item></root>";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true); // 关键!
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
NodeList items = doc.getElementsByTagName("item");
System.out.println(items.item(0).getTextContent()); // 输出 A
SAXParser 更轻量,适合大文件流式处理
SAX 是事件驱动模型,不构建内存树,适合只读、单次遍历、XML 文件较大(如上百 MB)的场景。
- 必须实现
DefaultHandler子类来响应startElement、endElement、characters等回调 -
characters()返回的 char[] 可能包含换行/空白,需用new String(ch, start, length).trim()提取有效内容 - 无法回溯或修改 XML,也不支持 XPath
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
SAXParser parser = factory.newSAXParser();
parser.parse(new InputSource(new StringReader(xml)), new DefaultHandler() {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if ("item".equals(qName)) {
System.out.println("Found item, id=" + attributes.getValue("id"));
}
}
});
常见错误:ParserConfigurationException / SAXParseException
这类异常往往不是 XML 内容错,而是工厂配置或输入源问题。
立即学习“Java免费学习笔记(深入)”;
-
ParserConfigurationException:通常因调用了不支持的 feature,例如factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)但在 JDK 8 默认 XML 解析器(Xerces)中未启用该 feature -
SAXParseException: Premature end of file:多因InputStream已被提前关闭或读空,检查是否重复调用close()或未重置流位置 - 中文乱码:确保
InputSource设置了编码,如source.setEncoding("UTF-8"),或 XML 声明中<?xml version="1.0" encoding="UTF-8"?>与实际一致
替代方案?注意 JAXP 的默认实现变化
JDK 9+ 中,javax.xml.parsers 默认使用内置的 jdk.xml.internal 实现,而非旧版 Xerces。这意味着:
- 部分老项目依赖的 Xerces 特有 system property(如
org.apache.xerces.xni.parser.XMLParserConfiguration)将失效 - 若需启用外部实体(极少见且危险),JDK 8 可用
setFeature("http://xml.org/sax/features/external-parameter-entities", true),但 JDK 17+ 默认禁用且不可绕过 - 对性能敏感场景,可考虑
javax.xml.stream.XMLInputFactory(StAX),它更可控、支持拉模式,但不在javax.xml.parsers包内
真正容易被忽略的是命名空间开关——哪怕你的 XML 看似没用 namespace,只要用了类似 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance",就必须设 setNamespaceAware(true),否则 getElementsByTagNameNS 失效,甚至 getTagName() 返回带前缀的怪名字。











