- 手动拼接 (DOM 方式):不推荐用于复杂结构,但有助于理解 XML 的基本组成。
- 使用标准库 (JAXB):Java 自带,非常适合将 Java 对象(包括包含 List 的对象)与 XML 进行绑定,这是推荐的方式。
- 使用第三方库 (Jackson/Gson):非常灵活和流行,通常用于 JSON,但对 XML 也有很好的支持。
准备工作:定义数据模型
无论使用哪种方法,我们都需要一个 Java 对象(POJO)来表示我们的数据,假设我们有一个 User 列表,每个 User 有 id, name, 和 email。

User.java
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement // 告诉 JAXB 这是一个根元素
public class User {
private int id;
private String name;
private String email;
// 必须有无参构造函数
public User() {}
public User(int id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
// 使用 @XmlElement 来指定 XML 元素的名称
@XmlElement
public int getId() { return id; }
public void setId(int id) { this.id = id; }
@XmlElement
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@XmlElement
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@Override
public String toString() {
return "User{" + "id=" + id + ", name='" + name + '\'' + ", email='" + email + '\'' + '}';
}
}
Main.java (包含我们的 List)
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// 准备数据
List<User> userList = new ArrayList<>();
userList.add(new User(1, "张三", "zhangsan@example.com"));
userList.add(new User(2, "李四", "lisi@example.com"));
userList.add(new User(3, "王五", "wangwu@example.com"));
// --- 接下来我们将用不同方法转换这个 userList ---
}
}
手动拼接 (DOM 方式)
这种方法通过创建 Document, Element 等对象来手动构建 XML 树,对于简单的结构尚可,但对于嵌套复杂的数据,代码会变得非常冗长且难以维护。
代码示例
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
// ... 在 Main.java 的 main 方法中添加 ...
// 1. 创建 DocumentBuilderFactory 和 DocumentBuilder
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// 2. 创建新的 Document 对象
Document doc = docBuilder.newDocument();
// 3. 创建根元素 <users>
Element rootElement = doc.createElement("users");
doc.appendChild(rootElement);
// 4. 遍历 List,为每个 User 创建一个 <user> 元素
for (User user : userList) {
Element userElement = doc.createElement("user");
// 创建 <id> 元素并设置值
Element idElement = doc.createElement("id");
idElement.appendChild(doc.createTextNode(String.valueOf(user.getId())));
userElement.appendChild(idElement);
// 创建 <name> 元素并设置值
Element nameElement = doc.createElement("name");
nameElement.appendChild(doc.createTextNode(user.getName()));
userElement.appendChild(nameElement);
// 创建 <email> 元素并设置值
Element emailElement = doc.createElement("email");
emailElement.appendChild(doc.createTextNode(user.getEmail()));
userElement.appendChild(emailElement);
// 将 <user> 元素添加到根元素 <users> 中
rootElement.appendChild(userElement);
}
// 5. 将 Document 转换为 XML 字符串
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(org.xml.transform.OutputKeys.INDENT, "yes"); // 美化输出
StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(doc), new StreamResult(writer));
String xmlString = writer.toString();
System.out.println("--- 手动拼接生成的 XML ---");
System.out.println(xmlString);
输出结果
--- 手动拼接生成的 XML ---
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<users>
<user>
<id>1</id>
<name>张三</name>
<email>zhangsan@example.com</email>
</user>
<user>
<id>2</id>
<name>李四</name>
<email>lisi@example.com</email>
</user>
<user>
<id>3</id>
<name>王五</name>
<email>wangwu@example.com</email>
</user>
</users>
缺点:
- 代码冗长,样板代码多。
- 容易出错,特别是处理特殊字符时。
- 对于大型或复杂的数据结构,维护成本极高。
使用标准库 (JAXB - Java Architecture for XML Binding)
JAXB 是 Java 标准库的一部分(从 Java 6 开始),专门用于在 Java 对象和 XML 之间进行转换,这是最推荐、最优雅的方式。
前提:如果你的项目使用 Java 9 或更高版本,JAXB 不再是默认包含的,你需要添加依赖。
Maven 依赖 (Java 9+)
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.1</version>
</dependency>
代码示例
我们还需要一个包装类来代表整个 XML 文档的根,因为 JAXB 需要一个根对象。
Users.java (包装类)
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@XmlRootElement(name = "users") // 指定根元素的名称
public class Users {
private List<User> users;
@XmlElement(name = "user") // 指定列表中每个元素的名称
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
Main.java 中的转换代码
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.StringWriter;
// ... 在 Main.java 的 main 方法中添加 ...
// 1. 创建包装对象并填充数据
Users usersWrapper = new Users();
usersWrapper.setUsers(userList);
// 2. 创建 JAXBContext
JAXBContext jaxbContext = JAXBContext.newInstance(Users.class);
// 3. 创建 Marshaller,用于将 Java 对象转换为 XML
Marshaller marshaller = jaxbContext.createMarshaller();
// 4. 设置输出格式,美化 XML
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// 5. 将对象转换为 XML 字符串
StringWriter writer = new StringWriter();
marshaller.marshal(usersWrapper, writer);
String xmlString = writer.toString();
System.out.println("--- JAXB 生成的 XML ---");
System.out.println(xmlString);
输出结果
--- JAXB 生成的 XML ---
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<users>
<user>
<id>1</id>
<name>张三</name>
<email>zhangsan@example.com</email>
</user>
<user>
<id>2</id>
<name>李四</name>
<email>lisi@example.com</email>
</user>
<user>
<id>3</id>
<name>王五</name>
<email>wangwu@example.com</email>
</user>
</users>
优点:
- 代码简洁:只需几行核心代码。
- 声明式:通过注解(如
@XmlRootElement)定义 XML 结构,代码与 XML 结构绑定清晰。 - 健壮:自动处理字符编码、特殊字符等问题。
- 标准:Java 官方推荐。
使用第三方库 (Jackson / Gson)
Jackson 和 Gson 是处理 JSON 的顶级库,它们也提供了对 XML 的支持(通过 jackson-dataformat-xml),如果你已经在项目中使用了这些库,这是一个不错的选择。
Maven 依赖
<!-- Jackson for XML -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.15.2</version>
</dependency>
代码示例
Jackson 在处理 List 时,默认会将其包装在一个名为 <list> 的元素中,我们可以使用 @JacksonXmlProperty 或自定义视图来改变它,但最简单的方式是直接使用。
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.StringWriter;
// ... 在 Main.java 的 main 方法中添加 ...
// 1. 创建 XmlMapper
XmlMapper xmlMapper = new XmlMapper();
// 2. 直接将 List 序列化为 XML
// 默认情况下,List 会被包装在 <list> 标签中
StringWriter writer = new StringWriter();
xmlMapper.writeValue(writer, userList);
String xmlString = writer.toString();
System.out.println("--- Jackson 生成的 XML (默认包装) ---");
System.out.println(xmlString);
// 如果想自定义根标签,可以创建一个包装类,就像 JAXB 的 Users 那样
// 然后序列化包装类对象
Users usersWrapper = new Users();
usersWrapper.setUsers(userList);
StringWriter writer2 = new StringWriter();
xmlMapper.writeValue(writer2, usersWrapper);
String xmlString2 = writer2.toString();
System.out.println("\n--- Jackson 生成的 XML (自定义根标签) ---");
System.out.println(xmlString2);
输出结果
userList 直接转换的结果:
--- Jackson 生成的 XML (默认包装) ---
<?xml version="1.0" encoding="UTF-8"?>
<list>
<item>
<id>1</id>
<name>张三</name>
<email>zhangsan@example.com</email>
</item>
<item>
<id>2</id>
<name>李四</name>
<email>lisi@example.com</email>
</item>
<item>
<id>3</id>
<name>王五</name>
<email>wangwu@example.com</email>
</item>
</list>
使用 Users 包装类后的结果:
--- Jackson 生成的 XML (自定义根标签) ---
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user>
<id>1</id>
<name>张三</name>
<email>zhangsan@example.com</email>
</user>
<user>
<id>2</id>
<name>李四</name>
<email>lisi@example.com</email>
</user>
<user>
<id>3</id>
<name>王五</name>
<email>wangwu@example.com</email>
</user>
</users>
注意:Jackson 默认使用 <item> 作为列表元素的标签,为了让它变成 <user>,你可以在 User 类上添加 @JacksonXmlProperty(localName = "user") 注解,或者在 Users 类的 getUsers() 方法上添加 @JacksonXmlElementWrapper(useWrapping = false)。
优点:
- 灵活性高:功能非常强大,配置选项丰富。
- 生态系统成熟:与 Jackson/Gson 的其他功能无缝集成。
- 性能通常很好。
总结与选择建议
| 特性 | 手动拼接 (DOM) | JAXB (标准库) | Jackson/Gson (第三方库) |
|---|---|---|---|
| 易用性 | 低 | 高 | 中 |
| 代码简洁性 | 差 | 优 | 良好 |
| 性能 | 一般 | 良好 | 通常最好 |
| 灵活性 | 差 | 良好 | 高 |
| 依赖 | 无 (JDK自带) | 无 (JDK自带,但Java9+需手动添加) | 需添加 jackson-dataformat-xml |
| 推荐场景 | 简单、一次性、无依赖要求的任务 | 企业级应用、标准化的数据交换 | 已在使用Jackson/Gson的项目、需要高度自定义XML格式的场景 |
最终建议:
- 对于大多数 Java 项目,首选 JAXB,它是官方标准,代码优雅,足以应对绝大多数需求。
- 如果你的项目已经深度集成了 Jackson 或 Gson,并且你享受其统一的 API,那么使用 Jackson for XML 是一个非常好的选择。
- 尽量避免手动拼接,除非你有一个非常简单的场景且不想引入任何依赖或学习新 API。
