JDOM是Java平台上一个专门为Java开发者设计的XML解析库,它不像DOM那样遵循W3C官方规范,也不像SAX那样采用事件驱动模型,而是充分利用Java语言自身的特性,比如集合框架、方法重载等,提供了一套更加符合Java编程习惯的API。本文将从JDOM的基本使用入手,逐步讲解文档构建、节点遍历、内容修改和格式化输出,最后将JDOM与同样流行的DOM4J库做一次全面对比,帮助你在项目中做出合适的技术选型。

一、JDOM快速入门:环境准备与基本概念
JDOM的核心设计理念是让XML操作变得简单直接。它没有直接实现DOM接口,而是定义了自己的一套类体系,比如Element、Attribute、Document等,这些类的命名和用法都非常贴近Java开发者的直觉。要使用JDOM,首先需要在项目中引入依赖,以Maven项目为例,在pom.xml中添加如下配置:
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6.1</version>
</dependency>需要注意的是,目前推荐使用的是jdom2,也就是JDOM 2.x版本,它对Java 5之后的泛型和枚举特性做了完整支持,性能也比1.x版本有明显提升。JDOM中有几个核心类需要重点理解:Document代表整个XML文档,是树形结构的根;Element对应XML中的元素节点;Attribute表示元素的属性;Text封装文本内容。理解了这几个类,JDOM的大部分API就已经掌握了。
JDOM提供了两种构建文档的方式:一种是基于SAX的SAXBuilder,另一种是基于DOM的DOMBuilder。前者在解析大文件时内存占用更小,后者则适合需要与其他DOM实现交互的场景。日常开发中绝大多数情况使用SAXBuilder即可。
二、JDOM核心操作详解:解析、遍历、修改与输出
1. 解析XML文件
使用SAXBuilder解析一个XML文件非常简单,几行代码就能拿到Document对象:
import org.jdom2.input.SAXBuilder;
import org.jdom2.Document;
import java.io.File;
public class JdomDemo {
public static void main(String[] args) throws Exception {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new File("books.xml"));
Element root = doc.getRootElement();
System.out.println("根元素名:" + root.getName());
}
}SAXBuilder的构造过程是线程不安全的,但build方法解析完成后得到的Document对象可以安全地在多个线程间共享,这一点在多线程环境下要特别注意。
2. 遍历节点与读取数据
JDOM获取子元素的方式非常直观,直接调用getChild或getChildren方法即可,返回类型就是Java标准的List,可以直接用增强for循环遍历:
List<Element> books = root.getChildren("book");
for (Element book : books) {
String id = book.getAttributeValue("id");
String title = book.getChildText("title");
String price = book.getChildText("price");
System.out.println("编号:" + id + ",书名:" + title + ",价格:" + price);
}相比原生DOM中繁琐的getElementsByTagName和NodeList,JDOM的API读起来几乎就是自然语言。如果需要获取更深层的元素,可以使用getChild("a").getChild("b")的链式调用,但要注意中间节点可能为null,做好空值判断。
3. 创建和修改XML文档
除了解析,JDOM创建新文档同样方便。下面的例子演示了如何从零构建一个XML文档并添加元素和属性:
Element root = new Element("library");
Document doc = new Document(root);
Element book = new Element("book");
book.setAttribute("id", "1001");
book.addContent(new Element("title").setText("Java编程思想"));
book.addContent(new Element("price").setText("108.00"));
root.addContent(book);修改操作也很直接,调用setText、setAttribute、removeChild等方法即可。这种所见即所得的编程模型,让JDOM特别适合需要对XML文档做频繁增删改操作的业务场景。
4. 格式化输出XML
处理完文档后,可以使用XMLOutputter将内容输出到文件或控制台,并支持自定义缩进和编码:
Format format = Format.getPrettyFormat();
format.setIndent(" ");
format.setEncoding("UTF-8");
XMLOutputter outputter = new XMLOutputter(format);
outputter.output(doc, new FileOutputStream("output.xml"));
outputter.output(doc, System.out);Format提供了两种预置格式:PrettyFormat会带缩进和换行,适合给人阅读;RawFormat则是紧凑输出,适合机器处理或对体积敏感的场景。
三、JDOM与DOM4J横向对比:如何选择
DOM4J同样是一个优秀的Java XML解析库,早期由JDOM社区分支发展而来,两者在API风格上有不少相似之处,但在细节上各有侧重。下面从几个关键维度进行对比。
| 对比维度 | JDOM | DOM4J |
|---|---|---|
| 设计理念 | 纯Java实现,API遵循Java命名规范 | 结合了DOM、SAX和JDOM的优点,抽象层次更灵活 |
| XPath支持 | 2.x版本开始支持XPath | 内置强大且成熟的XPath支持 |
| 性能表现 | 解析速度较快 | 综合性能略优,大数据量场景表现更好 |
| 与DOM互转 | 支持DOMBuilder双向转换 | 原生支持DOM、SAX多种接口适配 |
| 社区活跃度 | 更新较慢 | 更新相对更积极,使用更广泛 |
| 学习成本 | API直观简单,上手快 | API同样友好,但功能更多需要花时间了解 |
从API风格上看,两者都很好用,JDOM的命名更符合JavaBean规范,比如getChildText、getContentSize;DOM4J则提供了element、elementText等方法名。就XPath而言,DOM4J的支持历史更久,写法也更简洁:
// DOM4J中使用XPath定位节点
List<Node> nodes = doc.selectNodes("//book[price>50]");
Node first = doc.selectSingleNode("//book[@id='1001']/title");在性能方面,两个库都属于轻量级方案,解析中小型文档时差异可以忽略不计。只有在处理上百MB的大文件时,DOM4J配合其优化的遍历实现才略有优势。不过更极端的场景下,两者都不是最佳选择,此时应该考虑基于流的StAX或者SAX方案,避免整个文档加载进内存。
四、选型建议与实践经验
综合来看,两个库的能力高度重叠,选型时可以从以下几点考虑。如果项目对XPath查询有较高要求,或者团队已经在用DOM4J相关的生态组件,那么DOM4J是更稳妥的选择,Spring、Hibernate等知名框架内部也都依赖过DOM4J。如果只是做简单的配置文件读写、小型数据交换,JDOM的简洁API完全够用,而且代码可读性非常好。
还有一点值得注意,如果项目运行环境对依赖体积敏感,比如某些嵌入式场景,JDOM只有一个核心jar包,没有其他传递依赖,这一点比DOM4J更有优势。另外,对于JDK自带的方案,如果只是简单的XML处理,javax.xml.parsers加上Java 8之后的javax.xml.xpath也能应付,无需引入第三方库。
最后提醒一个实践中的常见坑:无论是JDOM还是DOM4J,解析不可信来源的XML时都要防范XXE注入攻击,务必禁用外部实体。以JDOM的SAXBuilder为例,可以这样配置:
SAXBuilder builder = new SAXBuilder();
builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
Document doc = builder.build(xmlInput);总的来说,JDOM和DOM4J都是成熟可靠的XML处理方案,没有绝对的优劣之分。理解它们各自的设计取向,结合项目的实际需求做选择,才能让工具发挥最大价值。