You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Maven构建时如何读取pom依赖的资源文件并合并为单个XML文件

实现方案

步骤1:编写XML合并逻辑代码

首先引入dom4j依赖用于XML处理,在你的pom.xml中加入以下依赖:

<dependency>
    <groupId>org.dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>2.1.4</version>
</dependency>
<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>2.0.0</version>
</dependency>

然后编写合并逻辑主类com.test.XmlMerger:

package com.test;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

import java.io.File;
import java.io.FileOutputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class XmlMerger {
    // 待扫描的XML资源路径
    private static final String SCAN_PATH = "test/";
    // 合并后输出路径,直接输出到构建后的classes目录,打包时自动打入jar
    private static final String OUTPUT_PATH = "target/classes/merge-all.xml";
    // XML根节点统一命名空间
    private static final String NAMESPACE = "http://xmlns.oracle.com/coherence/coherence-cache-config";

    public static void main(String[] args) throws Exception {
        SAXReader reader = new SAXReader();
        reader.setNamespaceAware(true);
        Document mergedDoc = null;

        // 扫描classpath下所有test目录的XML文件
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Enumeration<URL> resources = classLoader.getResources(SCAN_PATH);
        while (resources.hasMoreElements()) {
            URL resourceUrl = resources.nextElement();
            if (resourceUrl.getProtocol().equals("jar")) {
                // 处理第三方依赖jar包中的XML资源
                String jarPath = resourceUrl.getFile().split("!")[0].substring(5);
                try (JarFile jarFile = new JarFile(jarPath)) {
                    Enumeration<JarEntry> entries = jarFile.entries();
                    while (entries.hasMoreElements()) {
                        JarEntry entry = entries.nextElement();
                        String entryName = entry.getName();
                        if (entryName.startsWith(SCAN_PATH) && entryName.endsWith(".xml") && !entry.isDirectory()) {
                            Document doc = reader.read(jarFile.getInputStream(entry));
                            mergedDoc = mergeDocument(mergedDoc, doc);
                        }
                    }
                }
            } else if (resourceUrl.getProtocol().equals("file")) {
                // 处理当前项目自身resources下的XML资源
                File scanDir = new File(resourceUrl.toURI());
                File[] xmlFiles = scanDir.listFiles(f -> f.getName().endsWith(".xml"));
                if (xmlFiles != null) {
                    for (File file : xmlFiles) {
                        Document doc = reader.read(file);
                        mergedDoc = mergeDocument(mergedDoc, doc);
                    }
                }
            }
        }

        // 输出格式化后的合并XML
        if (mergedDoc != null) {
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
            try (FileOutputStream fos = new FileOutputStream(OUTPUT_PATH);
                 XMLWriter writer = new XMLWriter(fos, format)) {
                writer.write(mergedDoc);
            }
        }
    }

    private static Document mergeDocument(Document mergedDoc, Document newDoc) {
        if (mergedDoc == null) {
            return newDoc;
        }
        Element mergedRoot = mergedDoc.getRootElement();
        Element newRoot = newDoc.getRootElement();
        // 仅合并命名空间和根节点匹配的XML
        if (!mergedRoot.getNamespaceURI().equals(NAMESPACE) || !newRoot.getNamespaceURI().equals(NAMESPACE)) {
            return mergedDoc;
        }
        // 遍历根节点下的第一层子节点,合并内容
        for (Iterator<Element> it = newRoot.elementIterator(); it.hasNext(); ) {
            Element newChild = it.next();
            Element existChild = mergedRoot.element(newChild.getQName());
            if (existChild == null) {
                // 不存在的节点直接追加
                mergedRoot.add((Element) newChild.clone());
            } else {
                // 已存在的节点追加所有子元素
                for (Iterator<Element> subIt = newChild.elementIterator(); subIt.hasNext(); ) {
                    Element subNew = subIt.next();
                    existChild.add((Element) subNew.clone());
                }
            }
        }
        return mergedDoc;
    }
}

步骤2:绑定合并逻辑到Maven构建流程

修改pom.xml,添加exec插件将合并逻辑绑定到构建的process-classes阶段,构建时自动执行:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.1.0</version>
            <executions>
                <execution>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>java</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <mainClass>com.test.XmlMerger</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

效果验证

执行mvn package命令完成构建后,打开merge项目生成的jar包,即可在根目录看到合并完成的merge-all.xml文件,内容完全符合指定的子节点合并规则。

内容的提问来源于stack exchange,提问作者Babu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 23:09:01