W3C DOM 為跨語言設計,API 風格偏向 C/C++,Java 開發者用起來「水土不服」。JDOM 由 Brett McLaughlin 與 Jason Hunter 發起,專為 Java 設計,遵循 Java 集合框架慣例,支援 XPath、Namespace、Filter 等現代特性,是 Java 處理 XML 的首選輕量級庫。
jdom.jar)<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6</version>
</dependency>
| 類 | 包 | 職責 |
|---|---|---|
SAXBuilder | org.jdom.input | 基於 SAX 解析器構建 Document |
DOMBuilder | org.jdom.input | 從現有 DOM 樹構建 Document |
Document | org.jdom | XML 文檔根節點 |
Element | org.jdom | 元素節點(含屬性、子元素、文本) |
XMLOutputter | org.jdom.output | 將 Document 輸出為 XML 文本/流 |
XPathExpression | org.jdom.xpath | XPath 查詢(JDOM 2.x 新增) |
library.xml)<?xml version="1.0" encoding="UTF-8"?>
<books>
<book email="zhoujunhui">
<name>rjzjh</name>
<price>60.0</price>
</book>
<book email="author2">
<name>Java核心技術</name>
<price>89.9</price>
</book>
</books>
package com.example.xml;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
public class JDomParseDemo {
public static void main(String[] args) {
String xmlPath = "library.xml";
// 1. 建構解析器(false 表示不驗證 DTD)
SAXBuilder builder = new SAXBuilder(false);
try {
// 2. 解析生成 Document 對象
Document doc = builder.build(xmlPath);
// 3. 獲取根元素
Element root = doc.getRootElement(); //
// 4. 獲取所有 子元素
List bookList = root.getChildren("book");
// 5. 遍歷處理
for (Element book : bookList) {
// 5.1 讀取屬性
String email = book.getAttributeValue("email");
System.out.println("Author Email: " + email);
// 5.2 讀取子元素文本(自動 trim)
String name = book.getChildTextTrim("name");
System.out.println("Book Name: " + name);
// 5.3 修改子元素文本(僅內存中修改)
book.getChild("name").setText("Modified: " + name);
}
// 6. 格式化輸出回文件
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
outputter.output(doc, new FileOutputStream(xmlPath));
System.out.println("XML 更新完成!");
} catch (JDOMException | IOException e) {
e.printStackTrace();
}
}
}
// 默認 SAX 解析器(高性能、低內存)
SAXBuilder builder = new SAXBuilder();
// 指定 Xerces 解析器
SAXBuilder builder = new SAXBuilder("org.apache.xerces.parsers.SAXParser");
// 禁用驗證(加快解析速度)
SAXBuilder builder = new SAXBuilder(false);
getChildren(name):返回 List,支援泛型與增強 for 循環getChildTextTrim(name):一步到位獲取孫子文本並去除空白,避免空指針getAttributeValue(name):直接獲取屬性字符串,無屬性返回 nullsetText(content):修改元素文本內容,自動處理實體轉義// 緊湊格式(無縮進)
XMLOutputter outputter = new XMLOutputter(Format.getCompactFormat());
// 緩進格式(默認 2 空格,可自定義)
Format format = Format.getPrettyFormat();
format.setIndent(" "); // 4 空格
format.setEncoding("UTF-8");
XMLOutputter outputter = new XMLOutputter(format);
// 編譯 XPath 表達式
XPathExpression xpath = XPathFactory.instance().compile(
"//book[@email='zhoujunhui']/name",
Filters.element()
);
// 單次查詢
Element nameEl = xpath.evaluateFirst(doc);
if (nameEl != null) {
System.out.println("XPath 查詢結果: " + nameEl.getTextTrim());
}
// 列表查詢
List allPrices = XPathFactory.instance().compile("//price", Filters.element()).evaluate(doc);
allPrices.forEach(e -> System.out.println("Price: " + e.getText()));
| 問題 | 原因 | 解決方案 |
|---|---|---|
| 中文亂碼 | 輸出編碼未指定 | Format.getPrettyFormat().setEncoding("UTF-8") |
| 大文件 OOM | DOM 模型全量載入內存 | 改用 SAX/StAX 流式解析,或 JDOM 的 SAXHandler 自定義處理 |
| Namespace 失效 | 未正確處理命名空間 | 使用 Namespace.getNamespace(prefix, uri) 獲取 Namespace 對象傳給 getChild/Attribute |
| 實體解析錯誤 | DTD/Schema 未聲明 | 設置 EntityResolver 或禁用驗證 new SAXBuilder(false) |
JDOM 以「Java 原生」API 設計,讓 XML 處理回歸 Java 集合框架直覺體驗。掌握 SAXBuilder 解析、Element 導航修改、XMLOutputter 輸出三板斧,配合 XPath 強大查詢,即可應對 90% 的 XML 處理場景。對於超大文件或高性能場景,請轉向 StAX/SAX 流式處理。