Java+XSL合并多个XML文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java+XSL合并多个XML文件相关的知识,希望对你有一定的参考价值。

使用 Java 解析 XML 文件有许多成熟的工具,如 dom4j 等等。但在一些场景中,我们可能使用 Ant、Maven 等构建工具对多个 XML 文件进行合并,我们希望可以直接通过脚本文件,或者简单的程序就能完成这样的功能,那么使用 XSL 是一个非常不错的选择。本文将介绍通过简单的 Java 程序加上 XSL 文件来完成多个 XML 文件的合并操作。(XSL 是一种样式表语言,可用以描述如何显示一个 XML 文件)

背景

  1. Config.xml 文件的结构与 FinalConfig.xml 文件相似;
  2. 需要将 Config.xml 文件的内容合并到 FinalConfig.xml 文件;
  3. 若 FinalConfig.xml 文件中已存在 Config.xml 的内容,则覆盖。

目标:程序执行完成后,生成一个唯一的 XML 文件 FinalConfig.xml;

 

FinalConfig.xml 文件结构:

 1 <gameconfig>  
 2     <games>  
 3         <game>  
 4             <gameid>100</gameid>  
 5             <gamename>Fly to the Moon</gamename>  
 6             <gamedesc>This is Fly to the Moon</gamedesc>  
 7         </game>  
 8         <game>  
 9             <gameid>101</gameid>  
10             <gamename>10 Miles</gamename>  
11             <gamedesc>This is 10 Miles</gamedesc>  
12         </game>  
13     </games>  
14 </gameconfig>

Config.xml 文件结构:

1 <gameconfig>  
2     <games>  
3         <game>  
4             <gameid>100</gameid>  
5             <gamename>Fly to the Sun</gamename>  
6             <gamedesc>This is Fly to the Sun</gamedesc>  
7         </game>  
8     </games>  
9 </gameconfig>  

 

我们假定 gameid 是固定值,不会变。在合并完成后,<gameid>为 100 的 node 被更新。希望得到新的 FinalConfig.xml 文件如下:

 1 <gameconfig>  
 2     <games>  
 3         <game>  
 4             <gameid>100</gameid>  
 5             <gamename>Fly to the Sun</gamename>  
 6             <gamedesc>This is Fly to the Sun</gamedesc>  
 7         </game>  
 8         <game>  
 9             <gameid>101</gameid>  
10             <gamename>10 Miles</gamename>  
11             <gamedesc>This is 10 Miles</gamedesc>  
12         </game>  
13     </games>  
14 </gameconfig> 

 

一、Java 调用程序

 1 private void mergeXml(File xslFile, File configXml, File finalConfigXml){  
 2     DocumentBuilderFactory dbFac = DocumentBuilderFactory.newInstance();  
 3     DocumentBuilder builder;  
 4     Document destDoc = null;  
 5     FileInputStream input;  
 6     try{  
 7         builder = dbFac.newDocumentBuilder();  
 8         destDoc =  builder.parse(finalConfigXml);  
 9         if(!finalConfigXml.exists())   
10         {  
11             finalConfigXml.createNewFile();  
12         }  
13     input = new FileInputStream(xslFile);  
14     StreamSource source = new StreamSource(input);  
15     Transformer  transformer = TransformerFactory.newInstance().newTransformer(source);  
16     //为xsl文件设置变量"configXmlPath",将configXml文件的路径传递给xsl  
17     transformer.setParameter("configXmlPath", configXml.getPath());  
18     transformer.transform(new DOMSource(destDoc), new StreamResult(finalConfigXml));  
19     }catch(Exception e) {  
20         e.printStackTrace();  
21     }  
22 }  

 

二、XSL 文件

 1 <?xml version="1.0" encoding="UTF-8"?>  
 2 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
 3       
 4   <xsl:output method="xml" indent="yes"/>  
 5     
 6   <!-- pass the Config.xml file‘s path from Java code -->  
 7   <xsl:param name="configXmlPath"/>  
 8   <xsl:variable name="configXml" select="document($configXmlPath)"/>  
 9   
10   <xsl:template match="@* | node()">  
11     <xsl:copy>  
12       <xsl:apply-templates select="@* | node()"/>  
13     </xsl:copy>  
14   </xsl:template>  
15   
16   <xsl:template match="/gamedata">  
17         <xsl:copy>  
18           <xsl:apply-templates select="games" mode="updateGames"/>  
19         </xsl:copy>  
20   </xsl:template>  
21     
22   <xsl:template match ="games" mode="updateGames">  
23     <xsl:variable  name="gamesStr">  
24         <xsl:for-each select="$configXml/gamedata/games/game">  
25         <xsl:choose>  
26             <xsl:when test="gameid">  
27             <xsl:value-of select="concat(‘-‘,current()/gameid)"/>  
28             </xsl:when>  
29         </xsl:choose>  
30         </xsl:for-each>  
31     </xsl:variable>  
32     <games>  
33     <xsl:for-each select="game">  
34       <xsl:if test="not(contains($gamesStr,gameid))">  
35               <xsl:copy-of select="current()"/>  
36       </xsl:if>  
37     </xsl:for-each>  
38     <xsl:apply-templates select="$configXml/gamedata/games/game" />  
39     </games>  
40   </xsl:template>  
41 </xsl:stylesheet>  

 

三、XSL 文件解析

1.Java 传入参数 “configXmlPath” 为 Config.xml 文件的路径

1 <xsl:param name="configXmlPath"/> 

2.取出 Config.xml 文件中所有的 gameid,此处为增强处理,即 Config.xml 文件中可以存在多个 <game> 节点

1 <xsl:variable  name="gamesStr">  
2     <xsl:for-each select="$configXml/gamedata/games/game">  
3         <xsl:choose>  
4             <xsl:when test="gameid">  
5             <xsl:value-of select="concat(‘-‘,current()/gameid)"/>  
6             </xsl:when>  
7         </xsl:choose>  
8     </xsl:for-each>  
9 </xsl:variable>  

3.判断 FinalConfig.xml 的 <games> 子节点中是否存在当前的 gameid ,若不存在则复制

1 <xsl:for-each select="game">  
2   <xsl:if test="not(contains($gamesStr,gameid))">  
3      <xsl:copy-of select="current()"/>  
4   </xsl:if>  
5 </xsl:for-each>  

4.复制 Config.xml 文件中的所有 <game> 节点

<xsl:apply-templates select="$configXml/gamedata/games/game" />

 

(本文系从原博客迁移至此,并进行部分编辑。原文链接:http://thewaychung.iteye.com/blog/2072740)

以上是关于Java+XSL合并多个XML文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 XSL 合并 PDF 中的常用行

如何在 Java 中将 xsl 应用于 xml

PHP 合并XML / XSL

从 ditamap 创建 MERGED 文件,然后过滤它

XSLT 2 (Saxon):如何将多个文件读入内存

提供xml标头时,xsl模板匹配不起作用