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
相关产品推荐
相关产品推荐

