xml合并工具【原】
我的xml文章
xml转换: xml/map转换器
xml合并: xml合并
dupliate()方法思路图:
左报文为:
<PACKET>
<HEAD>
<REQUEST_TYPE>type1</REQUEST_TYPE>
<ERROR_CODE>0001</ERROR_CODE>
<ERROR_MESSAGE>message01</ERROR_MESSAGE> </HEAD>
<BODY>
<BOOK_LIST>
<BOOK>
<NAME>abc</NAME>
<PRICE>12.3</PRICE>
</BOOK>
<BOOK>
<NAME>same</NAME>
<PRICE>4</PRICE>
</BOOK>
</BOOK_LIST>
<VHL>
<A>1</A>
<B>3</B>
<C>4</C>
<D></D>
</VHL> </BODY>
</PACKET>
右报文为:
<PACKET>
<HEAD>
<REQUEST_TYPE>type2</REQUEST_TYPE>
<ERROR_CODE>0002</ERROR_CODE>
<ERROR_MESSAGE>message02</ERROR_MESSAGE> </HEAD>
<BODY>
<BOOK_LIST>
<BOOK>
<NAME>YUI</NAME>
<PRICE>12.3</PRICE>
</BOOK>
<BOOK>
<NAME>OIY</NAME>
<PRICE>4</PRICE>
</BOOK>
</BOOK_LIST>
<VHL>
<A>89</A>
<B>39</B>
<C></C>
<D>have</D>
<E>00</E>
</VHL> </BODY>
</PACKET>
最终效果为:
<?xml version="1.0" encoding="UTF-8"?>
<PACKET>
<HEAD>
<REQUEST_TYPE>type1|type2</REQUEST_TYPE>
<ERROR_CODE>0001</ERROR_CODE>
<ERROR_MESSAGE>message01</ERROR_MESSAGE> </HEAD>
<BODY>
<BOOK_LIST>
<BOOK>
<NAME>abc</NAME>
<PRICE>12.3</PRICE>
</BOOK>
<BOOK>
<NAME>same</NAME>
<PRICE>4</PRICE>
</BOOK>
<BOOK>
<NAME>YUI</NAME>
<PRICE>12.3</PRICE>
</BOOK>
<BOOK>
<NAME>OIY</NAME>
<PRICE>4</PRICE>
</BOOK>
</BOOK_LIST>
<VHL>
<A>1</A>
<B>3</B>
<C>4</C>
<D>have</D>
<E>00</E>
</VHL> </BODY>
</PACKET>
同事文亮大师代码,非常棒,值得借鉴.抽空再找个时间来分析.(mark)
package d; import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult; import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource; //******************************************************************
/**
* 类名:com.testdemo.pcis.common.utils.XMLMergeUtils
*
* <pre>
* 描述: xml文件内容合并
* 基本思路:
* public方法:
* 特别说明:
* 编写者:wlsun
* Email:wlsun@isoftstone.com
* 版权: Copyright (C) 2017 软通动力版权所有
* 创建时间:2017年2月23日 下午9:58:09
* 修改说明: 类的修改说明
* </pre>
*/
// *****************************************************************
public class XMLMergeUtils { /**
* ******************************************************************
* XML文件的合并处理,不做任何处理,直接合并 <br><pre>
* 方法xmlMerging2Str的详细说明 <br>
* 编写者:wlsun
* Email:wlsun@isoftstone.com
* 创建时间:2017年2月25日 下午3:45:40 </pre>
* @param mainXml 待合并处理的xml文件,合并后将更新此文件
* @param subXml 被合并的xml文件
* @return 合并成功返回合并版本,否则返回未合并报文第一个参数
* @throws Exception
*******************************************************************
*/
public static String xmlMerging2Str(String mainXml, String subXml) throws Exception {
return xmlMerging2Str(mainXml, subXml, new HashMap(), new HashMap());
} //******************************************************************
/**
* XML文件的合并处理 <br><pre>
* 方法xmlMerging2Str的详细说明 <br>
* 编写者:wlsun
* Email:wlsun@isoftstone.com
* 创建时间:2017年2月23日 下午10:38:37 </pre>
* @param mainXml 待合并处理的xml文件,合并后将更新此文件
* @param subXml 被合并的xml文件
* @param Map<String, String> dupliateNodes 合并节点不替换集合
* 当前节点相同需要合并 如<COVERAGE_LIST> 中的 <COVERAGE>需要合并
* @param Map<String, String> dupliateTexts 合并节点内容替换集合
* 当前节点相同不合并节点,合并指定节点内容处理如<HEAD> 中的<REQUEST_TYPE>
* @return 合并成功返回合并版本,否则返回未合并报文第一个参数
* @throws Exception
*/
//*****************************************************************
public static String xmlMerging2Str(String mainXml, String subXml,
Map<String, String> dupliateNodes, Map<String, String> dupliateTexts) throws Exception {
if(dupliateNodes == null) dupliateNodes = new HashMap<String, String>();
if(dupliateTexts == null) dupliateTexts = new HashMap<String, String>(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
System.err.println(e); // 出现异常时,输出异常信息
}
Document doc_main = null;
Document doc_vice = null;
// 获取两个XML文件的Document
try {
doc_main = db.parse(new InputSource(new StringReader(mainXml)));
doc_vice = db.parse(new InputSource(new StringReader(subXml)));
} catch (Exception e) {
e.printStackTrace();
System.err.println(e);
} // 获取两个文件的根节点
Element root_main = (Element) doc_main.getDocumentElement();
Element root_vice = (Element) doc_vice.getDocumentElement();
// 下面添加被合并文件根节点下的每个节点
NodeList messageItems = root_vice.getChildNodes();
int item_number = messageItems.getLength();
// 如果去掉根节点下的第一个节点,那么i从item_number开始,否则i从1开始
for (int i = 1; i < item_number; i = i + 2) {
// 调用dupliate(),依次复制被合并XML文档中根节点下的节点
Element messageItem = (Element) messageItems.item(i);
dupliate(doc_main, root_main, messageItem, dupliateNodes, dupliateTexts);
}
String result = outResultString(doc_main);
return result;
} /**
* ******************************************************************
* Document 转换为xml字符串内容<br><pre>
* 方法outResultString的详细说明 <br>
* 编写者:wlsun
* Email:wlsun@isoftstone.com
* 创建时间:2017年2月23日 下午10:38:37 </pre>
* @param Document doc_main
* @return String 说明
* @throws 异常类型 说明
*******************************************************************
*/
private static String outResultString(Document doc_main) throws TransformerFactoryConfigurationError, IOException {
// 创建输出(目标) 创建输出流 创建输出格式
StringWriter strWtr = new StringWriter();
StreamResult strResult = new StreamResult(strWtr);
TransformerFactory tfac = TransformerFactory.newInstance();
String result = "";
try {
javax.xml.transform.Transformer t = tfac.newTransformer();
// 设置xml的输出编码和是否去掉头文件
t.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty(OutputKeys.METHOD, "xml"); // xml, html, text
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
t.transform(new DOMSource(doc_main.getDocumentElement()), strResult);
// 输出格式化的串到目标中,执行后。
result = strResult.getWriter().toString();
} catch (Exception e) {
e.printStackTrace();
System.err.println("DocumentToXmlString error:" + e);
} finally {
if(strWtr != null) strWtr.close();
}
return result;
} //******************************************************************
/**
* 合并节点 <br><pre>
* 方法dupliate的详细说明 <br>
* 编写者:wlsun
* Email:wlsun@isoftstone.com
* 创建时间:2017年2月23日 下午10:19:39 </pre>
* @param Map<String, String> dupliateNodes 需合并节点不替换集合
* @param Map<String, String> dupliateTexts 需合并节点内容替换集合
* @return boolean 说明
* @throws Exception
*/
//*****************************************************************
private static boolean dupliate(Document doc_dup, Element father, Element son,
Map<String, String> dupliateNodes, Map<String, String> dupliateTexts) throws Exception {
boolean isdone = false;
Element parentElement = null; CopyChildElementObject childElementObject = isChildElement(father, son, dupliateNodes, dupliateTexts);
if (!childElementObject.isNeedCopy()) {
// 节点相同不用合并
isdone = true;
parentElement = childElementObject.getElement();
} else if (childElementObject.getElement() != null) {
parentElement = childElementObject.getElement();
} else {
parentElement = father;
} String son_name = son.getNodeName();
Element subITEM = null;
if (!isdone) {
subITEM = doc_dup.createElement(son_name);
//判断是否存在子节点,存在则不取节点文本,否则取文本节点
NodeList sub_messageItems = son.getChildNodes();
int sub_item_number = sub_messageItems.getLength();
if (sub_item_number < 2) {
subITEM.appendChild(doc_dup.createTextNode(son.getTextContent()));
} // 复制节点的属性
if (son.hasAttributes()) {
NamedNodeMap attributes = son.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
String attribute_name = attributes.item(i).getNodeName();
String attribute_value = attributes.item(i).getNodeValue();
subITEM.setAttribute(attribute_name, attribute_value);
}
}
parentElement.appendChild(subITEM);
} else {
subITEM = parentElement;
}
// 复制子结点
NodeList sub_messageItems = son.getChildNodes();
int sub_item_number = sub_messageItems.getLength();
if (sub_item_number < 2) {
// 如果没有子节点,则返回
isdone = true;
} else {
for (int j = 1; j < sub_item_number; j = j + 2) {
// 如果有子节点,则递归调用本方法
Element sub_messageItem = (Element) sub_messageItems.item(j);
isdone = dupliate(doc_dup, subITEM, sub_messageItem, dupliateNodes, dupliateTexts);
}
}
return isdone;
} //******************************************************************
/**
* 判断是否存在子节点 <br><pre>
* 方法isChildElement的详细说明 <br>
* 编写者:wlsun
* Email:wlsun@isoftstone.com
* 创建时间:2017年2月23日 下午10:20:12 </pre>
* @param Element father
* @param Element son
* @param Map<String, String> dupliateNodes 需合并节点不替换集合
* @param Map<String, String> dupliateTexts 需合并节点内容替换集合
* @return CopyChildElementObject 说明
* @throws 异常类型 说明
*/
//*****************************************************************
private static CopyChildElementObject isChildElement(Element father, Element son,
Map<String, String> dupliateNodes, Map<String, String> dupliateTexts) {
CopyChildElementObject childElementObject = new CopyChildElementObject(); NodeList messageItems = father.getChildNodes();
int item_number = messageItems.getLength();
// 首先遍历所有节点,查找是否有完全相同的节点,防止同一节点已定义多次
for (int i = 1; i < item_number; i = i + 2) {
Element messageItem = (Element) messageItems.item(i);
if (!messageItem.getNodeName().equals(son.getNodeName())) {
continue;
}
if (messageItem.isEqualNode(son)) {// 同时判断子节点是否一致
childElementObject.setNeedCopy(false);
childElementObject.setElement(messageItem);
return childElementObject;
}
}
for (int i = 1; i < item_number; i = i + 2) {
Element messageItem = (Element) messageItems.item(i);
// 判断节点是否处于同一级别
String msgItemNodeName = messageItem.getNodeName();
if (!msgItemNodeName.equals(son.getNodeName())) {
continue;
}
if (isEqualNode(messageItem, son)) {// 仅判断当前节点是否一致
if (hasEqualAttributes(messageItem, son)
&& !msgItemNodeName.equalsIgnoreCase(dupliateNodes.get(msgItemNodeName))) {
// 1、当前节点完全相同不需要合并
// 2、当前节点相同需要合并 如<COVERAGE_LIST> 中的 <COVERAGE>需要合并
// 3、当前节点相同不合并节点,合并指定节点内容处理如<HEAD> 中的<REQUEST_TYPE>
String keyName = messageItem.getParentNode().getNodeName() + "/" + msgItemNodeName;
if(keyName.equals(dupliateTexts.get(keyName))) {
messageItem.setTextContent(messageItem.getTextContent() + "|" + son.getTextContent());
} else {
//4、当前节点相同,报文一节点不存在内容,报文二节点存在内容,已存在内容的替换
if("".equals(messageItem.getTextContent())
&& !"".equals(son.getTextContent())) {
messageItem.setTextContent(son.getTextContent());
}
}
childElementObject.setNeedCopy(false);
childElementObject.setElement(messageItem);
return childElementObject;
} else {// 当前节点的属性不相同,需要合并
childElementObject.setNeedCopy(true);
childElementObject.setElement(father);
return childElementObject;
}
}
}
// 目标文档该节点不存在,需要合并到目标文档中
childElementObject.setNeedCopy(true);
childElementObject.setElement(father);
return childElementObject;
} //******************************************************************
/**
* 判断两个节点是否相同,未判断节点的属性<br><pre>
* 方法isEqualNode的详细说明 <br>
* 编写者:wlsun
* Email:wlsun@isoftstone.com
* 创建时间:2017年2月23日 下午10:20:35 </pre>
* @param 参数类型 参数名 说明
* @return boolean 说明
*/
//******************************************************************
private static boolean isEqualNode(Node arg0, Node arg) {
if (arg == arg0) {
return true;
}
if (arg.getNodeType() != arg0.getNodeType()) {
return false;
} if (arg0.getNodeName() == null) {
if (arg.getNodeName() != null) {
return false;
}
} else if (!arg0.getNodeName().equals(arg.getNodeName())) {
return false;
} if (arg0.getLocalName() == null) {
if (arg.getLocalName() != null) {
return false;
}
} else if (!arg0.getLocalName().equals(arg.getLocalName())) {
return false;
} if (arg0.getNamespaceURI() == null) {
if (arg.getNamespaceURI() != null) {
return false;
}
} else if (!arg0.getNamespaceURI().equals(arg.getNamespaceURI())) {
return false;
} if (arg0.getPrefix() == null) {
if (arg.getPrefix() != null) {
return false;
}
} else if (!arg0.getPrefix().equals(arg.getPrefix())) {
return false;
} if (arg0.getNodeValue() == null) {
if (arg.getNodeValue() != null) {
return false;
}
} else if (!arg0.getNodeValue().equals(arg.getNodeValue())) {
return false;
}
return true;
} //******************************************************************
/**
* 判断节点的属性是否相同<br><pre>
* 方法hasEqualAttributes的详细说明 <br>
* 编写者:wlsun
* Email:wlsun@isoftstone.com
* 创建时间:2017年2月23日 下午10:22:29 </pre>
* @param 参数类型 参数名 说明
* @return boolean 说明
* @throws 异常类型 说明
*/
//*****************************************************************
private static boolean hasEqualAttributes(Node arg0, Node arg) {
NamedNodeMap map1 = arg0.getAttributes();
NamedNodeMap map2 = arg.getAttributes();
int len = map1.getLength();
if (len != map2.getLength()) {
return false;
} for (int i = 0; i < len; i++) {
Node n1 = map1.item(i);
if (n1.getNodeName() != null) {
Node n2 = map2.getNamedItem(n1.getNodeName());
if (n2 == null) {
return false;
} else if (!n1.getNodeValue().equals(n2.getNodeValue())) {
return false;
}
}
}
return true;
} public static void main(String[] args) {
try { FileHelper fileHelper = new FileHelper();
String sourcefile = "src/d/file1.xml";
String main = fileHelper.readTxt(sourcefile, "UTF-8");
String targetfile = "src/d/file2.xml";
String sub = fileHelper.readTxt(targetfile, "UTF-8"); long start = new Date().getTime();
Map<String, String> dupliateNodes = new HashMap<String, String>();
dupliateNodes.put("COVERAGE", "COVERAGE"); Map<String, String> dupliateTexts = new HashMap<String, String>();
dupliateTexts.put("HEAD/REQUEST_TYPE", "HEAD/REQUEST_TYPE"); String mergStr = XMLMergeUtils.xmlMerging2Str(main, sub, dupliateNodes, dupliateTexts);
long end = new Date().getTime();
System.out.println(mergStr);
System.out.println((end-start));
} catch (Exception e) {
e.printStackTrace();
}
}
} //******************************************************************
/**
* 类名:com.isoftstone.pcis.common.utils.CopyChildElementObject <pre>
* 描述: 复制子节点对象, 记录该节点是否需要复制, 记录该节点的父节点
* 基本思路:
* public方法:
* 特别说明:
* 编写者:wlsun
* Email:wlsun@isoftstone.com
* 版权: Copyright (C) 2017 软通动力版权所有
* 创建时间:2017年2月23日 下午10:39:45
* 修改说明: 类的修改说明
* </pre>
*/
//*****************************************************************
class CopyChildElementObject {
private boolean needCopy = true;// 记录该节点是否需要复制
private Element element = null;// 记录该节点的父节点 public CopyChildElementObject() {
super();
} public boolean isNeedCopy() {
return needCopy;
} public void setNeedCopy(boolean needCopy) {
this.needCopy = needCopy;
} public Element getElement() {
return element;
} public void setElement(Element element) {
this.element = element;
}
}
xml合并工具【原】的更多相关文章
- 高通AR和友盟SDK的AndroidManifest.xml合并
高通AR和友盟SDK的AndroidManifest.xml合并 因为高通的AR在android中一开始就要启动,所有主Activity要设置为高通的Activity,即android:name=&q ...
- CSS 和 JS 文件合并工具
写 CSS 和 JavaScript 的时候, 我们会遇到一个两难的局面: 要么将代码写在一个大文件, 要么将代码分成多个文件. 前者导致文件难以管理, 代码复用性差, 后者则因为需要在载入多个文件令 ...
- Java XML解析工具 dom4j介绍及使用实例
Java XML解析工具 dom4j介绍及使用实例 dom4j介绍 dom4j的项目地址:http://sourceforge.net/projects/dom4j/?source=directory ...
- svn的差异查看器和合并工具换成BCompare.exe
svn的差异查看器和合并工具换成BCompare.exe
- Mergely – 免费的在线文档对比和合并工具
任何类型的文件(无论是否代码),我们可能要比较不同的版本,看发生了什么变化. 有些编辑器都有这个内置功能,其中一些则没有. Mergely 是一个免费使用的 Web 应用程序,帮你你迅速作出文档的差异 ...
- Vimdiff---VIM的比较和合并工具
本文来自IBMDW http://www.ibm.com/developerworks/cn/linux/l-vimdiff/ 源程序文件(通常是纯文本文件)比较和合并工具一直是软件开发过程中比较 ...
- C# 版dll 程序集合并工具
C# 版dll 程序集合并工具 最近要开发一个控件给同事用,开发中会引用一些第三方DLL,这样交给用户很不方便,希望的效果是直接交付一个DLL文件.网上找了一些资料. 1. 使用 Cost ...
- CSS Sprite小图片自动合并工具
css-sprite是将css样式中零星的小图标,小图片合并成大图显示,这样能减小服务器并发连接数,减小服务器负载和带宽使用,有很高的实用价值.这里介绍一些自动合并图片并生成样式的工具. NodeJS ...
- 文件合并工具DiffMerge发布4.2版本
DiffMerge一直是文件对比合并工具的佼佼者,其最大特点是多文件对比与合并,并提供可视化界面用于编辑. 此次DiffMerge v4.2发布,提高了文件差异对比,并提供了快速匹配功能,以及更好的用 ...
随机推荐
- Ajax cross domain
xhrFields:{ withCredentials:true}, https://stackoverflow.com/questions/2054316/sending-credentials-w ...
- SpringMvc常见问题汇总
1.Service类未用@Service注解2016-10-26 17:31:36 [org.springframework.web.context.ContextLoader]-[ERROR] Co ...
- ESXi内虚拟机带快照与不带快照的情况下简单性能对比.
1. 两个虚拟机配置相同都为2vCPU 8G内存 一个虚拟机内包含较多的快照且有内容梗概 一个虚拟机不包含快照直接只有一个虚拟机的vmdk磁盘文件 操作系统未windows server 2008r2 ...
- CentOS7 安装 Jenkins
1. 安装java环境, 自己的虚拟机里面前期已经安装好了 检查一下: [root@centos74 ~]# java -versionopenjdk version "1.8.0_131& ...
- java List<String>的初始化
今天在处理生成excel的时候用到了java的list,但是需要直接赋值固定的几个变量,如果先初始化然后add的方法: List<String> name = new ArrayList( ...
- asp.net 连接SQL Server 数据库并进行相关操作
asp.net 连接数据库,操作数据库主要需要两个类,一个是SqlConnection,一个是SqlCommand SqlConnection用于连接数据库,打开数据库,关闭数据库. 连接数据库需要特 ...
- MyBatis在表名作为参数时遇到的问题
之前在用MyBatis的时候没用过表名作为参数,最近使用到了. 基于注释使用MyBatis的Dao层代码如下: @Repository public interface Base1102Dao { @ ...
- Java中如何输出对勾,ASCII编码与字符串相互转换
Java中如何输出对勾? 最简单的方法是,从那个地方拷贝一个对勾的字符,然后System.out.println("√"); 但是心里总会担心,万一机器不认这个字符该怎么办?(可能 ...
- sql server 小技巧(8) visual studio 2013里使用Sql server compact 4.0及发布问题处理
1. 安装 Microsoft SQL Server Compact 4.0 https://www.microsoft.com/zh-cn/download/confirmation.aspx?i ...
- 【原创】python多线程测试接口性能
除了使用性能测试工具进行性能测试,我们也可以直接用python多线程进行性能测试. 下面,使用这几个模块,对一个查询接口做性能测试: requests:发送http请求 json:返回的字符串转换成j ...