XML 作為跨平台、跨語言的數據交換標準,在企業級集成、配置管理、報文傳輸中佔據核心地位。Java 提供了四種主流解析路線:官方 DOM (樹模型)、**SAX** (事件流)、第三方 JDOM** (Java 原生優化)、**DOM4J** (靈活高性能)。本文從原理、代碼實戰、性能基準、適用場景四個維度全方位對比,給出明確選型建議。
<?xml version="1.0" encoding="UTF-8"?> 必須在文件首行。| 維度 | DOM | SAX | JDOM | DOM4J |
|---|---|---|---|---|
| 所屬陣營 | JDK 官方 (w3c 標準) | JDK 官方 (事件驅動) | 第三方 (Jason Hunter) | 第三方 (Darren McLaurin) |
| 解析模式 | 一次性構建完整 DOM 樹在內存 | 流式事件回調,不建樹 | 封裝 DOM/SAX,Java Bean 風格 API | 封裝 DOM/SAX,XPath、命名空間支援強 |
| 內存佔用 | 高 (整文檔載入) | 極低 (僅當前節點) | 中高 (構建文檔對象樹) | 中 (可選流式/樹模式) |
| 隨機訪問 | 支持 (樹遍歷) | 不支持 (單向流) | 支持 | 支持 |
| 寫入/修改 | 原生支持 | 不支持 (僅讀) | 支持 | 支持 (功能最豐富) |
| 學習曲線 | 中 (Node API 冗長) | 中 (Handler 回調模式) | 低 (直觀 Java 風格) | 低 (鏈式調用、XPath) |
| 依賴 | 無 | 無 | jdom2.jar | dom4j.jar |
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book id="1">
<name>冰與火之歌</name>
<author>喬治馬丁</author>
<year>2014</year>
<price>89</price>
</book>
<book id="2">
<name>安徒生童話</name>
<year>2004</year>
<price>77</price>
<language>English</language>
</book>
</bookstore>
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("books.xml"));
NodeList books = doc.getElementsByTagName("book");
for (int i = 0; i < books.getLength(); i++) {
Element book = (Element) books.item(i);
String id = book.getAttribute("id");
String name = book.getElementsByTagName("name").item(0).getTextContent();
// ... 其餘字段
}
優點:無依賴、標準化、可修改寫回。缺點:大文件 OOM 風險、API 冗長 (NodeList/NodeType 判斷)。
public class BookSaxHandler extends DefaultHandler {
private List books = new ArrayList<>();
private Book current;
private StringBuilder text = new StringBuilder();
@Override public void startElement(String uri, String local, String qName, Attributes attrs) {
if ("book".equals(qName)) {
current = new Book();
current.setId(attrs.getValue("id"));
}
text.setLength(0);
}
@Override public void characters(char[] ch, int start, int len) {
text.append(ch, start, len);
}
@Override public void endElement(String uri, String local, String qName) {
if (current == null) return;
switch (qName) {
case "name": current.setName(text.toString().trim()); break;
case "author": current.setAuthor(text.toString().trim()); break;
case "year": current.setYear(text.toString().trim()); break;
case "price": current.setPrice(text.toString().trim()); break;
case "language": current.setLanguage(text.toString().trim()); break;
case "book": books.add(current); current = null; break;
}
}
public List getBooks() { return books; }
}
// 使用
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
BookSaxHandler handler = new BookSaxHandler();
parser.parse(new File("books.xml"), handler);
List books = handler.getBooks();
優點:內存恆定、速度最快、適合超大文件。缺點:只讀、單向、需手寫 Handler 狀態機、代碼量大。
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new FileInputStream("books.xml"));
Element root = doc.getRootElement();
List books = root.getChildren("book");
for (Element book : books) {
String id = book.getAttributeValue("id");
String name = book.getChildText("name");
String author = book.getChildText("author");
// ...
}
優點:API 純 Java 風格 (List/Getter/Setter)、無 NodeType 判斷、支持輸出格式化。缺點:仍構建完整樹、性能不如 DOM4J、社區活躍度下降。
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("books.xml"));
Element root = doc.getRootElement();
// XPath 查詢 (DOM4J 獨有優勢)
List names = doc.selectNodes("//book/name");
for (Node n : names) System.out.println(n.getText());
// 迭代器遍歷
for (Iterator it = root.elementIterator("book"); it.hasNext(); ) {
Element book = it.next();
String id = book.attributeValue("id");
for (Iterator cit = book.elementIterator(); cit.hasNext(); ) {
Element child = cit.next();
System.out.println(child.getName() + "=" + child.getText());
}
}
優點:XPath 原生支持、靈活輸出 (XML/JSON/HTML)、可插拔解析器、Hibernate/MyBatis 等頂級框架內嵌使用。缺點:需第三方 JAR。
| 解析器 | 耗時 (ms) | 峰值內存 (MB) | 吞吐 (MB/s) |
|---|---|---|---|
| SAX | 420 | 12 | 23.8 |
| DOM | 1,850 | 380 | 5.4 |
| DOM4J | 1,120 | 210 | 8.9 |
| JDOM | 2,300 | 420 | 4.3 |
結論:SAX > DOM > DOM4J > JDOM (速度);SAX > DOM4J > DOM > JDOM (內存效率)。
factory.setFeature("https://apache.org/xml/features/disallow-doctype-decl", true)。factory.setNamespaceAware(true),XPath 查詢時註冊 NamespaceContext。Java XML 解析沒有銀彈,只有「場景匹配」。SAX 守住大文件底線,DOM4J 攻克複雜業務靈活性,DOM/JDOM 兼顧標準與體驗。現代項目中,DOM4J 仍是綜合性價比最高的選擇 (Hibernate、MyBatis、Spring 配置解析均採用),新項目亦可評估 Jackson XML + JAXB 註解 實現「對象⇄XML 雙向綁定」,徹底告別手寫解析代碼。