`
GhostFromheaven
  • 浏览: 393992 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

java合并两个XML文件

阅读更多




package cs.edu.hust.cs.j2se.test;

import java.io. *; //Java基础包,包含各种IO操作 
import java.util. *; //Java基础包,包含各种标准数据结构操作 
import javax.xml.parsers. *; //XML解析器接口 
import org.w3c.dom. *; //XML的DOM实现 
import javax.xml.transform. *;
import javax.xml.transform.dom. *;
import javax.xml.transform.stream. *;

/**
 * XML文件合并工具类

 * @author GhostFromHeaven
 */
public class XMLMergeUtil {
    
    /**
     * XML文件的合并处理
     * @param mainFileName 待合并处理的xml文件,合并后将更新此文件
     * @param subFilename 被合并的xml文件
     * @return 合并成功返回true,否则返回false
     * @throws Exception
     */
    public static boolean isMerging(String mainFileName, String subFilename)
            throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = null;
        try {
            db = dbf.newDocumentBuilder();
        } catch (ParserConfigurationException pce) {
            System.err.println(pce); // 出现异常时,输出异常信息
        }
        Document doc_main = null;
        Document doc_vice = null;
        // 获取两个XML文件的Document
        try {
        	doc_main = db.parse(mainFileName);
            doc_vice = db.parse(subFilename);
        } catch (DOMException dom) {
            System.err.println(dom.getMessage());
        } catch (Exception ioe) {
            System.err.println(ioe);
        }
        // 获取两个文件的根节点
        
        Element root_main = doc_main.getDocumentElement();
        Element root_vice = doc_vice.getDocumentElement();
        // 下面添加被合并文件根节点下的每个节点
        NodeList messageItems = root_vice.getChildNodes();
        int item_number = messageItems.getLength();
        // 如果去掉根节点下的第一个节点,那么i从3开始,否则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);
        }
        // 调用 write To(),将合并得到的Document写入目标XML文档
        boolean isWritten = writeTo(doc_main, mainFileName);
        return isWritten;
    }
    
    /**
     *
     * @param doc_dup
     * @param father
     * @param son
     * @return
     * @throws Exception
     */
    private static boolean dupliate(Document doc_dup, Element father, Element son)
            throws Exception {
        boolean isdone = false;
        Element parentElement = null;
        
        DuplicateChildElementObject childElementObject = isChildElement(father, son);
        if(!childElementObject.isNeedDuplicate()){
            //节点相同不用合并
            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);
            // 复制节点的属性
            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);
            }
        }
        
        
        return isdone;
    }

    private static boolean writeTo(Document doc, String fileName) throws Exception {
        boolean isOver = false;
        DOMSource doms = new DOMSource(doc);
        File f = new File(fileName);
        StreamResult sr = new StreamResult(f);
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer t = tf.newTransformer();
            Properties properties = t.getOutputProperties();
            properties.setProperty(OutputKeys.ENCODING, "UTF-8");
            t.setOutputProperties(properties);
            t.transform(doms, sr);
            isOver = true;
        } catch (TransformerConfigurationException tce) {
            tce.printStackTrace();
        } catch (TransformerException te) {
            te.printStackTrace();
        }
        return isOver;
    }
    
    private static DuplicateChildElementObject isChildElement(Element father, Element son){
        
        DuplicateChildElementObject  childElementObject = new DuplicateChildElementObject();
        
        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.setNeedDuplicate(false);
                childElementObject.setElement(messageItem);
                return childElementObject;
            }
        }
        for (int i = 1; i < item_number; i = i + 2) {
            Element messageItem = (Element) messageItems.item(i);
            //判断节点是否处于同一级别
            if(!messageItem.getNodeName().equals(son.getNodeName())){
                continue;
            }
            if(isEqualNode(messageItem,son)){//仅判断当前节点是否一致
                if(hasEqualAttributes(messageItem,son)){//当前节点完全相同不需要合并
                    childElementObject.setNeedDuplicate(false);
                    childElementObject.setElement(messageItem);
                    return childElementObject;
                }else{//当前节点的属性不相同,需要合并
                    childElementObject.setNeedDuplicate(true);
                    childElementObject.setElement(father);
                    return childElementObject;
                }
            }    
        }
        //目标文档该节点不存在,需要合并到目标文档中
        childElementObject.setNeedDuplicate(true);
        childElementObject.setElement(father);
        return childElementObject;
    }
    
    /**
     * 判断两个节点是否相同,未判断节点的属性
     * @param arg0
     * @param arg
     * @return
     */
    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;
    }
    
    /**
     * 判断节点的属性是否相同
     * @param arg0
     * @param arg
     * @return
     */
    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 {

            String sourcefile = "d:/a.xml"; 
            String targetfile = "d:/b.xml";
            
            boolean isdone = XMLMergeUtil.isMerging(sourcefile, targetfile);
            
            if (isdone)
                System.out.println("XML files have been merged.");
            else
                System.out.println("XML files have NOT been merged.");
        
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/**
 * 复制子节点对象
 * @author Administrator
 *
 */
class DuplicateChildElementObject{
    private boolean needDuplicate = true;//记录该节点是否需要复制
    private Element element = null;//记录该节点的父节点

    public DuplicateChildElementObject() {
        super();
    }

    public boolean isNeedDuplicate() {
        return needDuplicate;
    }

    public void setNeedDuplicate(boolean needDuplicate) {
        this.needDuplicate = needDuplicate;
    }

    public Element getElement() {
        return element;
    }

    public void setElement(Element element) {
        this.element = element;
    }
}







分享到:
评论
2 楼 GhostFromheaven 2012-11-10  
mooshadow 写道
你好,首先感谢你的程序。我最近也碰到了这个问题,用了你的程序之后,出现错误如下:
java.lang.ClassCastException: org.apache.xerces.dom.DeferredCDATASectionImpl incompatible with org.w3c.dom.Element
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:115)
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:116)
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:116)
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:116)
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:116)
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:116)
at merge.XMLMergeUtilUseDOM.isMerging(XMLMergeUtilUseDOM.java:56)
at merge.XMLMergeUtilUseDOM.main(XMLMergeUtilUseDOM.java:277)

可能是我的targetfile中包含了CDATA信息,没法正常解析?希望能得到您的帮助。


xml包含CDATA信息的情况,有的xml包是不支持的,就向错误提示说的:org.apache.xerces.dom.DeferredCDATASectionImpl incompatible with org.w3c.dom.Element

DeferredCDATASectionImpl 和 Element 是不兼容的。需要转换,或者用DeferredCDATASectionImpl 读取,而不是Element。
1 楼 mooshadow 2012-10-19  
你好,首先感谢你的程序。我最近也碰到了这个问题,用了你的程序之后,出现错误如下:
java.lang.ClassCastException: org.apache.xerces.dom.DeferredCDATASectionImpl incompatible with org.w3c.dom.Element
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:115)
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:116)
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:116)
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:116)
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:116)
at merge.XMLMergeUtilUseDOM.dupliate(XMLMergeUtilUseDOM.java:116)
at merge.XMLMergeUtilUseDOM.isMerging(XMLMergeUtilUseDOM.java:56)
at merge.XMLMergeUtilUseDOM.main(XMLMergeUtilUseDOM.java:277)

可能是我的targetfile中包含了CDATA信息,没法正常解析?希望能得到您的帮助。

相关推荐

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part2

    本书共分4部分,从xml、servlet、jsp和应用的角度向读者展示了java web开发中各种技术的应用,循序渐进地引导读者快速掌握java web开发。.  本书内容全面,涵盖了从事java web开发所应掌握的所有知识。在知识的讲解...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part3

    本书共分4部分,从xml、servlet、jsp和应用的角度向读者展示了java web开发中各种技术的应用,循序渐进地引导读者快速掌握java web开发。.  本书内容全面,涵盖了从事java web开发所应掌握的所有知识。在知识的讲解...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part4

    本书共分4部分,从xml、servlet、jsp和应用的角度向读者展示了java web开发中各种技术的应用,循序渐进地引导读者快速掌握java web开发。.  本书内容全面,涵盖了从事java web开发所应掌握的所有知识。在知识的讲解...

    java源码包---java 源码 大量 实例

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part5

    本书共分4部分,从xml、servlet、jsp和应用的角度向读者展示了java web开发中各种技术的应用,循序渐进地引导读者快速掌握java web开发。.  本书内容全面,涵盖了从事java web开发所应掌握的所有知识。在知识的讲解...

    JAVA上百实例源码以及开源项目

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    fuego-diff:用于计算 XML 文档树之间结构差异的 Java 库

    Fuego Diff 是一个工具和库,用于计算两个 XML 文档之间的差异(有点像diff工具对文本文件的作用),以及将编辑应用于文档(如patch工具)。 因此,它可以用于例如由不同人修改的文档之间的三向合并。 功能亮点: ...

    java源码包4

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    java源码包3

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    java源码包2

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    JAVA上百实例源码以及开源项目源代码

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    Java右键弹出菜单源码 简单 Java圆形按钮实例代码,含注释 两个目标文件,自绘button。 Java圆形电子时钟源代码 1个目标文件 内容索引:JAVA源码,系统相关,电子钟 用JAVA编写的指针式圆形电子钟,效果图如下所示,...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    Java右键弹出菜单源码 简单 Java圆形按钮实例代码,含注释 两个目标文件,自绘button。 Java圆形电子时钟源代码 1个目标文件 内容索引:JAVA源码,系统相关,电子钟 用JAVA编写的指针式圆形电子钟,效果图如下所示,...

    XML轻松学习手册--XML肯定是未来的发展趋势,不论是网页设计师还是网络程序员,都应该及时学习和了解

    比如,两个相同行业不同地区的人使用同一个DTD文件来作为文档创建规范,那么他们的数据就很容易交换和共享。网上有其他人想补充数据,也只需要根据公用的DTD规范来建立文档,就立刻可以加入。 目前,已经有数量众多...

    java jdk实列宝典 光盘源代码

    15 applet java可以编写两类程序,applications和applet,applications可以在控制台直接运行,与其他高级编程语言没有太大区别,而java的特色在于它具有编制小应用程序的功能,applet可以在internet上传输并在兼容...

    XML实用大全----xml详细参考书

    第3章 第一个XML文档... 34 3.1 Hello XML. 34 3.1.1 创建一个简单的XML文档... 34 3.1.2 保存XML文件... 35 3.1.3 将XML文件装入Web浏览器... 35 .2 考察简单的XML文档... 37 3.3 赋于XML标记以意义... 39 ....

    Java面试宝典-经典

    3、用jdom解析xml文件时如何解决中文问题?如何解析? 114 4、编程用JAVA解析XML的方式. 115 5、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式? 117 七. 流行的框架与新技术 117 1、谈谈你...

    Java面试宝典2010版

    3、用jdom解析xml文件时如何解决中文问题?如何解析? 114 4、编程用JAVA解析XML的方式. 115 5、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式? 117 七. 流行的框架与新技术 117 1、谈谈你...

Global site tag (gtag.js) - Google Analytics