在Java开发中,合并多个xml文件是常见的需求,比如整合多个模块的配置片段、汇总多份数据报表等。合并时需要处理不同xml的文档结构,保留原有节点的层级关系,同时避免结构冲突。下面将介绍基于Java标准库实现xml合并的完整方案。

合并思路说明
合并多个xml文件的核心步骤如下:
- 使用
DocumentBuilder解析每个待合并的xml文件,得到对应的Document对象 - 创建一个目标
Document对象作为合并后的容器,可自定义根节点名称 - 遍历每个源
Document的子节点,将需要合并的节点导入到目标Document中 - 使用
Transformer将合并后的Document输出为xml文件
完整实现代码
1. 基础合并方法实现
以下代码实现将多个xml文件合并到一个新的根节点下,保留所有源文件的子节点结构:
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.util.List;
public class XmlMerger {
/**
* 合并多个xml文件
* @param xmlFilePaths 待合并的xml文件路径列表
* @param targetRootName 合并后xml的根节点名称
* @param outputPath 合并后xml的输出路径
*/
public static void mergeXmlFiles(List<String> xmlFilePaths, String targetRootName, String outputPath) {
try {
// 创建DocumentBuilder工厂
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
// 忽略命名空间验证,避免部分xml解析报错
dbFactory.setNamespaceAware(false);
DocumentBuilder db = dbFactory.newDocumentBuilder();
// 创建目标Document,设置根节点
Document targetDoc = db.newDocument();
Element rootElement = targetDoc.createElement(targetRootName);
targetDoc.appendChild(rootElement);
// 遍历每个待合并的xml文件
for (String filePath : xmlFilePaths) {
File xmlFile = new File(filePath);
if (!xmlFile.exists()) {
System.out.println("文件不存在:" + filePath);
continue;
}
// 解析当前xml文件
Document sourceDoc = db.parse(xmlFile);
// 获取源xml的根节点
Element sourceRoot = sourceDoc.getDocumentElement();
// 导入源根节点到目标Document,deep为true表示导入所有子节点
Node importedNode = targetDoc.importNode(sourceRoot, true);
// 将导入的节点添加到目标根节点下
rootElement.appendChild(importedNode);
}
// 将合并后的Document输出为xml文件
writeDocumentToXml(targetDoc, outputPath);
System.out.println("xml合并完成,输出路径:" + outputPath);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 将Document对象写入xml文件
* @param doc 待输出的Document对象
* @param outputPath 输出文件路径
*/
private static void writeDocumentToXml(Document doc, String outputPath) throws TransformerException {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
// 设置输出属性,美化格式
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
// 设置编码
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(outputPath));
transformer.transform(source, result);
}
public static void main(String[] args) {
// 待合并的xml文件路径列表
List<String> xmlFiles = List.of("file1.xml", "file2.xml", "file3.xml");
// 合并后的根节点名称
String targetRoot = "mergedRoot";
// 输出文件路径
String outputFile = "merged.xml";
// 执行合并
mergeXmlFiles(xmlFiles, targetRoot, outputFile);
}
}
2. 待合并的示例xml文件
以下是两个示例xml文件的内容,用于测试合并效果:
file1.xml内容:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<server>
<host>127.0.0.1</host>
<port>8080</port>
</server>
</config>
file2.xml内容:
<?xml version="1.0" encoding="UTF-8"?>
<user>
<name>testUser</name>
<age>25</age>
</user>
3. 合并后的输出结果
执行上述代码后,merged.xml的内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<mergedRoot>
<config>
<server>
<host>127.0.0.1</host>
<port>8080</port>
</server>
</config>
<user>
<name>testUser</name>
<age>25</age>
</user>
</mergedRoot>
注意事项
- 如果待合并的xml文件有命名空间,需要开启
dbFactory.setNamespaceAware(true),避免解析时出现节点命名空间冲突 - 如果多个xml文件存在相同名称的节点需要去重,可以在导入节点前先判断目标根节点下是否已存在同名节点,再做合并或跳过处理
- 解析xml时如果文件较大,建议采用流式解析(如SAX)避免内存溢出,上述方案适合中小型xml文件合并
- 如果源xml文件的根节点结构相同,需要调整导入逻辑,将源根节点的子节点导入到目标根节点下,而不是导入整个源根节点
同结构xml合并调整方案
如果多个xml文件的根节点名称相同,需要合并根节点下的子节点,可以修改合并逻辑如下:
// 替换上述mergeXmlFiles方法中的节点导入部分
for (String filePath : xmlFilePaths) {
File xmlFile = new File(filePath);
if (!xmlFile.exists()) {
System.out.println("文件不存在:" + filePath);
continue;
}
Document sourceDoc = db.parse(xmlFile);
Element sourceRoot = sourceDoc.getDocumentElement();
// 获取源根节点下的所有子节点
NodeList childNodes = sourceRoot.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
// 跳过空白文本节点
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
Node importedNode = targetDoc.importNode(childNode, true);
rootElement.appendChild(importedNode);
}
}
}
调整后的逻辑会将每个源xml根节点下的子节点直接合并到目标根节点下,适合多个相同结构的配置片段合并场景。
Javaxml_mergeDocumentBuilderNodeTransformer修改时间:2026-07-02 09:30:29