JDOM 并不是 Java 标准库自带的 API,而是一个专门为 Java 开发者设计的 XML 解析库。它把 XML 文档中的元素、属性、注释、文本等内容映射为 Java 对象,常见的类包括 Document、Element、Attribute 和 Text。与 W3C 标准的 DOM 接口相比,JDOM 不再依赖接口继承和工厂方法,使用时可以直接 new 对象,也可以把元素列表当作普通的 List 来遍历。下面以 JDOM 2.x 为例,说明从引入依赖到读取、遍历 XML 文件的完整过程。

一、JDOM的核心定位与DOM、SAX的差异
JDOM 的设计目标很明确:让 Java 程序员操作 XML 时像操作普通 Java 集合一样自然。DOM 解析器生成的是 org.w3c.dom.Document 对象,节点类型复杂,经常需要判断 nodeType 再强制转换,代码里到处是 getFirstChild 和 getNodeName。JDOM 把这些细节封装起来,直接提供 getChildren 方法返回 List 集合,getChildText 方法能一步取到子元素文本。这种简化在读取配置文件、解析接口响应等场景下非常明显。
在依赖方面,JDOM 2.x 的核心包是 jdom2,Maven 项目加入以下依赖即可使用。JDOM 底层默认使用 JAXP 的 SAX 解析器读取 XML,因此它兼具 DOM 的树模型和 SAX 的解析效率。使用 JDOM 时通常只需记住三个核心类:SAXBuilder 负责构建,Document 表示整篇文档,Element 表示元素节点。
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6.1</version>
</dependency>
二、用JDOM读取XML文件的基础流程
先准备一个简单的 books.xml,结构如下。外层是 books 根元素,内部包含两个 book 子元素,每个 book 有一个 id 属性,以及 title、author、price 三个子元素。
<books>
<book id="1">
<title>JDOM入门</title>
<author>张三</author>
<price>39.00</price>
</book>
<book id="2">
<title>XML实战</title>
<author>李四</author>
<price>49.00</price>
</book>
</books>
针对这个文件,可以用下面的 Java 代码完成解析和遍历。SAXBuilder 的 build 方法接收 File 对象,构建出 Document 后通过 getRootElement 获得根节点,再逐一读取子元素和属性。
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import java.io.File;
import java.util.List;
public class JdomReadExample {
public static void main(String[] args) throws Exception {
SAXBuilder builder = new SAXBuilder();
Document document = builder.build(new File("books.xml"));
Element root = document.getRootElement();
System.out.println("根元素: " + root.getName());
List<Element> bookList = root.getChildren("book");
for (Element book : bookList) {
String id = book.getAttributeValue("id");
String title = book.getChildText("title");
String author = book.getChildText("author");
String price = book.getChildText("price");
System.out.println("ID=" + id + ", 书名=" + title + ", 作者=" + author + ", 价格=" + price);
}
}
}
上面代码中 getChildren("book") 返回所有直接子元素中名为 book 的元素列表,可以直接用 foreach 遍历。getChildText("title") 会返回第一个 title 子元素的文本内容;如果子元素不存在,返回 null。getAttributeValue("id") 用于读取属性值,属性不存在时同样返回 null。这套方法覆盖了大多数普通 XML 数据读取需求。
这里要特别注意 getChildText 和 getText 的区别。getChildText 只读取某个子元素的文本,不受混合内容影响;getText 会返回当前元素下所有文本内容,但如果元素里同时包含子元素和文本,可能需要用 getContent 遍历 Text 节点。对纯数据型 XML 来说,getChildText 是最常用的取文本方法。
如果需要把 XML 转成业务对象,可以在遍历时创建对应的 Book 类并赋值。JDOM 不会像 JAXB 那样自动绑定字段,但手动映射的代码非常直观。例如将上面的 title、author、price 存入 Book 实体,再放入 List 返回,整个解析逻辑仍然集中在一个方法里。相比 DOM 的 NodeList 遍历,代码可读性明显更高。解析大文件时要注意 SAXBuilder 默认不开启 DTD 校验,如果 XML 包含外部实体,建议关闭外部实体加载,或使用 XMLReaderJDOMFactory 定制解析器,避免 XXE 风险。
三、处理命名空间与混合内容的常见问题
很多配置文件会使用默认命名空间,这时直接调用 getChild("book") 可能取不到元素,因为子元素自动带上了命名空间。JDOM 2 提供了 Namespace 类来解决这个问题。先通过 Namespace.getNamespace 获得对应 URI 的命名空间对象,再使用重载的 getChildren("book", ns) 和 getChildText("title", ns) 进行查找。
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.jdom2.input.SAXBuilder;
import java.io.StringReader;
import java.util.List;
public class JdomNamespaceExample {
public static void main(String[] args) throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<books xmlns=\"http://ipipp.com/books\">" +
"<book id=\"1\"><title>JDOM入门</title></book>" +
"</books>";
SAXBuilder builder = new SAXBuilder();
Document document = builder.build(new StringReader(xml));
Element root = document.getRootElement();
Namespace ns = Namespace.getNamespace("http://ipipp.com/books");
List<Element> bookList = root.getChildren("book", ns);
for (Element book : bookList) {
String title = book.getChildText("title", ns);
String id = book.getAttributeValue("id");
System.out.println("ID=" + id + ", 书名=" + title);
}
}
}
上面的 XML 字符串中,books 元素声明了 xmlns 默认命名空间 http://ipipp.com/books。如果不传 Namespace,JDOM 会认为你在查找无命名空间的 book 元素,因此返回空列表或 null。传入 Namespace 对象后,getChildren 才能匹配到正确元素。对于有前缀的命名空间,例如 xmlns:p="http://ipipp.com/p",同样可以使用 Namespace.getNamespace("p", "http://ipipp.com/p") 来构建。
另一个容易忽略的问题是混合内容。JDOM 的 getText 方法会提取当前元素下所有 Text 节点,但不会保留子元素的边界。例如一个段落里既有文字又有链接标签,getText 会把文字和链接文本拼在一起,但无法知道哪部分是链接。遇到这种结构,应该使用 getContent 方法遍历 Element、Text、CDATA 等节点,按顺序处理。JDOM 还支持 getChildren 过滤出指定类型,也可以使用 DescendantFilter 等 API 做复杂筛选。
编码方面,SAXBuilder 会根据 XML 声明和底层解析器自动识别字符集,一般不需要额外设置。如果从字节流读取但没有 XML 声明,可能出现中文乱码,此时建议用 Reader 并指定编码,或直接使用 File 让解析器读取文件头。JDOM 的 Document 和 Element 都不是线程安全的,解析出的对象不应该在多线程中无保护地共享,但可以每个线程独立 build 和修改。需要写出 XML 时,可以使用 XMLOutputter 将 Document 输出到文件或控制台,格式化和编码都可以配置。
四、JDOM、DOM、SAX之间的选择
JDOM 与 DOM 都是树模型,解析后整个文档会驻留内存。对几十 KB 到几 MB 的配置文件、接口响应、模板文件,JDOM 的易用性非常突出。DOM 的优势在于它是 W3C 标准接口,不依赖第三方库,且可以在 JavaScript、Python 等语言中保持类似 API;但 Java 代码里 DOM 的冗长让不少开发者感到繁琐。SAX 和 StAX 是事件驱动或流式解析,内存占用低,适合几十 MB 以上的大文件,但编码复杂度高。
| 解析方式 | 内存占用 | 易用性 | 适用场景 |
|---|---|---|---|
| JDOM | 高 | 高 | 中小型文件,需随机访问和修改 |
| DOM | 高 | 中 | 标准接口,跨语言一致性 |
| SAX | 低 | 低 | 大文件,顺序读取 |
| StAX | 低 | 中低 | 大文件,可控制拉取 |
从实际项目角度,如果 XML 文件很小且需要频繁随机访问节点、修改后写回,推荐使用 JDOM。如果 XML 结构复杂、需要严格遵循标准接口,或者环境不允许引入第三方库,则选择 DOM。如果只需要提取少量字段且文件很大,使用 SAX 或 StAX 更合适。JDOM 本身也可以与 DOM 互转,通过 DOMBuilder 和 DOMOutputter 实现 Document 对象转换,方便在两个模型之间迁移。
最后总结一下,JDOM 用普通 Java 对象和集合操作 XML,学习成本低,代码可读性好,非常适合中小型 XML 数据处理。掌握 SAXBuilder、Document、Element、Namespace 这几个核心类,就能完成大多数读取、遍历、过滤和修改需求。使用时注意命名空间匹配、空文本判断和线程安全,基本可以避开常见的坑。
JDOM解析XMLJava XML解析JDOM教程修改时间:2026-10-04 01:09:16