`
GhostFromheaven
  • 浏览: 396983 次
  • 性别: 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 使用POI合并两个word文档.docx

    Java 使用 POI 合并两个 Word 文档 Java 是一种流行的编程语言,POI(Poor Obfuscation Implementation)是一个流行的 Java 库,用于操作 Microsoft Office 文件,包括 Word 文档。合并两个 Word 文档是指将两个...

    java实现多个docx文档合并(基于docx4j)

    在Java编程环境中,合并多个docx文档是一项常见的需求,特别是在处理大量Word文档的工作场景中。本文将详细介绍如何使用Java和docx4j库来实现这一功能。docx4j是一个强大的开源库,专门用于处理Microsoft Office ...

    java合并xml1

    一个XML文件由元素(Elements)、属性(Attributes)、文本内容(Text Content)等组成。在Java中,我们通常使用DOM(Document Object Model)或SAX(Simple API for XML)解析器来处理XML文档。DOM将整个XML文档...

    合并2个结构相同的xml文件

    -- 合并两个XML文件中相应元素的子节点 --&gt; *"/&gt; ('file2.xml')/root2/*[local-name() = current()/local-name()]"&gt; ()"/&gt; &lt;!-- 复制所有其他属性和文本节点 --&gt; * | node()"&gt; * | node()"/&gt; ...

    Java DOM 生成XML

    在Java中,DOM API被包含在`javax.xml.parsers`和`org.w3c.dom`这两个包中。 DOM API的核心类包括`DocumentBuilderFactory`、`DocumentBuilder`和`Document`。首先,`DocumentBuilderFactory`用于创建`...

    java使用stax技术操作XML文档.doc

    StAX提供了两个级别的API:基于指针的API和基于迭代器的API。 基于指针的API通过XMLStreamReader实现,它就像是一个指针,始终指向已解析的最新标记。开发者可以查询解析器状态,获取前一个标记的信息,并继续处理...

    poi合并多个word文档并设置页码

    在"poi合并多个word文档并设置页码"这个主题中,我们将深入探讨如何利用POI API来实现这两个功能。 首先,让我们讨论如何合并多个Word文档。Apache POI提供了一个名为`XWPFDocument`的类,它代表一个Open XML格式的...

    Jacob Word excel 转PDF 合并PDF文件

    这个插件使得Word文档可以被保存为PDF或XPS(XML Paper Specification)格式,这两种格式都适合于网络共享和打印,因为它们能保留原始文档的布局和格式。 对于Excel到PDF的转换,过程类似。Jacob会调用Excel的COM...

    Hadoop示例程序合并文件

    Hadoop主要由两个关键部分组成:Hadoop Distributed File System (HDFS) 和 MapReduce。HDFS是分布式存储系统,而MapReduce则负责分布式计算。 2. HDFS特性: - 分布式:HDFS将大文件分割成块,并将这些块复制到...

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

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

    利用POI合并多个Excel表

    以下是一个简单的示例,演示如何合并两个Excel文件中的第一张工作表: ```java import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.File; import java.io....

    java dom xml

    1. **DOM API**: Java中的DOM解析主要涉及`javax.xml.parsers`和`org.w3c.dom`这两个包。首先,`DocumentBuilderFactory`用于创建一个`DocumentBuilder`实例,该实例能够解析XML文件并构建`Document`对象。然后,`...

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

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

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

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

    使用XStream 多集合生成xml

    这将生成两个XML字符串,分别表示用户列表和地址列表。如果想将这两个集合合并到一个XML文档中,可能需要创建一个包含这两个集合的容器类,如`DataContainer`,并将其转换为XML: ```java public class Data...

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

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

    java使用itext实现pdf文件下载

    Itext是一个强大的库,它允许开发者在Java环境中创建、编辑和修改PDF文档。本教程将详细讲解如何使用Itext库实现PDF文件的下载,包括通过系统路径下载和通过浏览器下载两种方式。 首先,我们需要了解Itext的基本...

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

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

    java源码包2

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

Global site tag (gtag.js) - Google Analytics