dom4j合并xml报文
报文转换思想:
先将报文最长转化为dom对象
再将报文进行对比不存在的就新增进去
原dom对象xml报文:
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<hgwTerminalRestartResponse xmlns="http://www.example.org/MobileLoadingMachine/">
<responseStr xmlns=""><?xml version="1.0" encoding="UTF-8"?> <root><resultCode>3</resultCode></root></responseStr>
</hgwTerminalRestartResponse>
</soapenv:Body>
</soapenv:Envelope>
例如要合并的doc2
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body id="1">
<hgwTerminalRestartResponse xmlns="http://www.example.org/MobileLoadingMachine/">
<responseStr xmlns=""><?xml version="1.0" encoding="UTF-8"?> <root><resultCode>3</resultCode></root></responseStr>
</hgwTerminalRestartResponse>
<sss xmlns="http://www.example.org/MobileLoadingMachine/">
<responseStr xmlns=""><?xml version="1.0" encoding="UTF-8"?> <root><resultCode>3</resultCode></root></responseStr>
</sss>
</soapenv:Body>
</soapenv:Envelope>
先将2个xml报文转为doc对象:
Document doc = null ;
try {
doc = DocumentHelper.parseText(str);
System.out.println("=================="+ doc.asXML());
}catch(DocumentException e){
}
//打印所有college节点值,如果有的话
Document doc1 = null ;
try {
doc1 = DocumentHelper.parseText(str1);
System.out.println("=================="+ doc1.asXML());
}catch(DocumentException e){
}
然后在将其对比取根目录对比
/**
*
* @param oridoc 旧的文档对象
* @param newdoc 新的文档对象
*/
public static void compare(Document oridoc,Document newdoc){
Element oriRootElement = oridoc.getRootElement();
Element newRootElement = newdoc.getRootElement();
if(oriRootElement.getQualifiedName().equals(newRootElement.getQualifiedName())){
addAttrAndName( oriRootElement, newRootElement);
for(Iterator<Element> sonElement = newRootElement.elementIterator() ; sonElement.hasNext();) {
Element son = sonElement.next();
Element element= oriRootElement.element(son.getQName());
if(element==null){
oriRootElement.add((Element) son.clone());
return;
}
List<String> nodeList = new ArrayList<String>();
Set<String> pathSet = new HashSet<String>();
leafXmlCompare(son,element);
}
}
};
/**
*
* @param oriRootElement 旧的元素
* @param newElement 新的元素
*/
public static void addAttrAndName(Element oriRootElement,Element newElement){
//获取所有的命名空间
for( Object ob :newElement.content() )
if( ob instanceof Namespace) {
System.out.println(" ##Namespace:"+ ((Namespace) ob).getPrefix());
Namespace namespace= oriRootElement.getNamespaceForPrefix(((Namespace) ob).getPrefix());
if(namespace==null){
oriRootElement.add(((Namespace) ob));
}
}
//获取所有的属性
for(Object obj :newElement.attributes() )
if( obj instanceof Attribute) {
Attribute newAttribute= (Attribute) obj;
Attribute oriAttribute= oriRootElement.attribute(newAttribute.getQName());
if(oriAttribute==null){
oriRootElement.add((Attribute) newAttribute.clone());
}
}
}
判断子元素是否存在不存在的直接新增到旧的报文对象去,注意这里新增dom4j要用clone()方法才行,
在判断命名空间和属性是否存在,新的存在在遍历新的命名空间和属性,如果对应的旧的不存在就新增进去
同理下面就遍历到子节点
/**
* XML的Element路径遍历获取
* @param element 新的当前节点元素
* @param oriElement 旧的当前节点元素
*/
private static void leafXmlCompare(Element element, Element oriElement){
addAttrAndName( oriElement, element);
if(element.isTextOnly()){
return;
}else if(StringUtils.isNotBlank(element.getText())){
return;
}
for(Iterator<Element> sonElement = element.elementIterator() ; sonElement.hasNext();) {
Element son = sonElement.next();
Element element1= oriElement.element(son.getQName());
System.out.println("=========="+son.getQName());
System.out.println("=========="+son.getQualifiedName());
if(element1==null){
System.out.println("=========="+oriElement.getQualifiedName());
oriElement.add((Element) son.clone());
return;
}
leafXmlCompare(son,element1);
}
}
根据递归方法遍历新的报文最后遍历到文本停止:如果旧的不存在新的节点就新增进去。最后就是合并的新的报文。如果json的话也可以按照这个,转换成json对象。不过这里我转换json比较复杂不是用xml的方式,后续可参考我写的json合并报文。
最终实现的效果打印出来:
至于求报文节点的结构的可以将合并的报文:
/**
* XML的Element路径遍历获取
* @param element 当前节点元素
* @param nodeList 全部路径节点集合
* @param pathSet 用于节点去重
*/
private static void leafXml(Element element, List<String> nodeList, Set<String> pathSet,String qualifiedName){
// 数组节点不重复保存
System.out.println("==================");
System.out.println("==================");
List<String> sss=element.attributes();
System.out.println("//sss:"+element.getNodeType());
List<Attribute> attributes = element.attributes();
//打印属性
for (Attribute attr : attributes) {
System.out.println(attr.getName()+":"+attr.getValue());
}
System.out.println("//telephone:getName:"+element.getName());
System.out.println(" ##getNodeType:"+element.getNodeType());
System.out.println(" ##getTextTrim:"+element.getTextTrim());
System.out.println(" ##getNamespaceURI:"+element.getNamespaceURI());
System.out.println(" ##getNodeTypeName:"+element.getNodeTypeName());
System.out.println(" ##getQualifiedName:"+element.getQualifiedName());
System.out.println(" ##getUniquePath:"+element.getUniquePath());
System.out.println(" ##getPath:"+element.getPath());
String lastChar = element.getUniquePath().substring(element.getUniquePath().length() - 3); // => "1"
System.out.println(" ##lastChar:"+lastChar);
if(lastChar.contains("[1]")){
qualifiedName=qualifiedName+"/"+element.getQualifiedName()+lastChar;
}else if(lastChar.contains("[2]")){
qualifiedName=qualifiedName+"/"+element.getQualifiedName()+lastChar;
}else if(lastChar.contains("[3]")){
qualifiedName=qualifiedName+"/"+element.getQualifiedName()+lastChar;
}else if(lastChar.contains("[4]")){
qualifiedName=qualifiedName+"/"+element.getQualifiedName()+lastChar;
}else{
qualifiedName=qualifiedName+"/"+element.getQualifiedName();
}
System.out.println(" ##qualifiedName:"+qualifiedName);
if(element.isTextOnly()){
if(!pathSet.contains(element.getPath())){
nodeList.add(element.getUniquePath());
pathSet.add(element.getPath());
}
return;
}else if(StringUtils.isNotBlank(element.getText())){
if(!pathSet.contains(qualifiedName)){
nodeList.add(qualifiedName);
pathSet.add(qualifiedName);
}
return;
}
for(Iterator<Element> sonElement = element.elementIterator() ; sonElement.hasNext();) {
Element son = sonElement.next();
leafXml(son,nodeList,pathSet,qualifiedName);
}
}
然后用这个nodeList求出来