改进的Java XML文件合并工具类

工作中遇到需要合并XML的问题,遂从网上查找相关资料,

1、 《 XML merging made easy  

2 、《java中合并xml文档的设计与实现 

 

测试后发现均不符合实际需求,实际需求如下:

 

file1.xml: 

<root>
<a>
<b name="1"/>
</a>
<d />
<e id='1' />
</root>
file2.xml:
<root>
<a>
<b name="22"/>
</a>
<d name="qq"/>
<e id='1' />
</root>

合并后需要得到:
<root>
<a>
<b name="22" />
<b name="1" />
</a>
<d name="qq" />
<e id="1" />
<d />
</root>

基于《java中合并xml文档的设计与实现  》的介绍对代码进行改进,完成了此功能,代码如下:

 

 

package davyxie;

import java.io.File;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.DOMException;
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;

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

 * @author davyxie
 */
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;
    }
}

/**
 * 复制子节点对象
 * @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;
    }

   
}

 

 

测试方法:

    public static void main(String[] args) {
        try {

            String sourcefile = "E:/file1.xml";
            String targetfile = "E:/file2.xml";
           
            boolean isdone = XMLMerge.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();
        }
    }

Java实现导出合并行列工具类可以使用POI库来实现。POI是一个开源项目,可以用于操作Microsoft Office格式的文档,如Word、Excel、PowerPoint等。 首先,需要引入POI库的jar包。可以使用Maven来管理jar包的依赖,将以下代码添加到pom.xml文件即可。 ``` <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> ``` 接下来,可以创建一个工具类,实现导出Excel并合并单元格的功能。以下代码实现了将二维数组导出到Excel合并第一行和第一列单元格的功能。 ``` import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelUtil { public static void export(String[][] data, String fileName) throws IOException { Workbook wb = new XSSFWorkbook(); Sheet sheet = wb.createSheet("Sheet1"); for (int i = 0; i < data.length; i++) { String[] rowData = data[i]; for (int j = 0; j < rowData.length; j++) { String cellData = rowData[j]; Cell cell = sheet.createRow(i).createCell(j); cell.setCellValue(cellData); CellStyle cellStyle = wb.createCellStyle(); cellStyle.setAlignment(CellStyle.ALIGN_CENTER); cell.setCellStyle(cellStyle); } } CellRangeAddress region = new CellRangeAddress(0, 0, 0, 0); sheet.addMergedRegion(region); region = new CellRangeAddress(0, data.length - 1, 0, 0); sheet.addMergedRegion(region); FileOutputStream fileOut = new FileOutputStream(fileName); wb.write(fileOut); fileOut.close(); wb.close(); } } ``` 这个工具类,先使用XSSFWorkbook类创建一个新的Excel workbook对象,然后创建一个新的sheet,遍历二维数组data并将其写入到sheet。在写入单元格数据的同时,创建了一个单元格样式CellStyle对象并设置了文本居的样式。 接着,使用CellRangeAddress类来合并第一行和第一列单元格,并将合并后的区域添加到sheet。最后,将数据写入到文件并关闭workbook对象。 使用这个ExcelUtil工具类可以轻松地将数据导出到Excel并合并单元格。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值