天天看點

Dom4j節點處理器的實作

Dom4j為XML文檔解析提供了強大的API支援,在實際開發中,為了處理友善,常常以節點元素(Element)為機關進行處理,并且結合資料庫和Java技術,為節點生成ID屬性。這樣,就很有必要在Dom4j的基礎上,重新封裝一些适用需要的方法,以提高開發效率。下面是我利用業餘時間做的一個Dom4j節點處理器工具類的實作。希望能節省開發人員寶貴時間。

說明:為了寫起來友善,可以單獨運作,我沒有寫單獨的測試類,實際用的時候,删除掉測試main()和test()方法即可。

注釋很詳細,不用廢話了。下面是處理器的實作:

測試用的xml:

輸出三個測試對象 

----------srcXml------------ 

<?xml version="1.0" encoding="GBK"?> 

<doc> 

    <person> 

        <name>某人</name> 

        <adds> 

            <add ID="10001"> 

                <BS>10001</BS> 

                <note>鄭州市經三路</note> 

            </add> 

            <add ID="10002"> 

                <BS>10002</BS> 

                <note>西安市太白路</note> 

            <add ID=""> 

                <note>空ID節點啊</note> 

            <add> 

        </adds> 

    </person> 

    <other> 

        <name ID="HEHE">ASDF</name> 

        <name>空ID節點啊</name> 

    </other> 

</doc> 

----------nodeXml1------------ 

----------nodeXml2------------ 

</doc>

處理器的實作類:

package com.topsoft.icib.common.utils; 

import org.dom4j.*; 

import org.apache.commons.logging.Log; 

import org.apache.commons.logging.LogFactory; 

import org.apache.commons.lang.StringUtils; 

import java.util.Random; 

import java.util.Iterator; 

import java.util.ArrayList; 

/** 

* Created by IntelliJ IDEA.<br> 

* <b>User</b>: leizhimin<br> 

* <b>Date</b>: 2008-3-27 18:42:39<br> 

* <b>Note</b>: XML節點處理器,包含XML元素的CRUD方法。 

*/ 

public class XmlNodeHandler { 

    private static Log log = LogFactory.getLog(XmlNodeHandler.class); 

    /** 

     * 在xml的指定位置插入一個元素 

     * 

     * @param srcXml  原xml 

     * @param nodeXml 元素xml 

     * @param xpath   要插入元素父節點的位置 

     * @return 原xml插入節點後的完整xml文檔 

     */ 

    public static String addElement(String srcXml, String nodeXml, String xpath) { 

        String resultXml = null; 

        try { 

            Document docSrc = DocumentHelper.parseText(srcXml); 

            Document docNode = DocumentHelper.parseText(nodeXml); 

            Element parentElement = (Element) docSrc.getRootElement().selectSingleNode(xpath); 

            parentElement.add(docNode.getRootElement()); 

            resultXml = docSrc.asXML(); 

        } catch (DocumentException e) { 

            log.error("在文檔" + xpath + "位置添加新節點發生異常,請檢查!"); 

            System.out.println(e.getMessage()); 

            e.printStackTrace(); 

        } 

        return resultXml; 

    } 

     * 删除xml文檔中指定ID的元素 

     * @param srcXml    原xml 

     * @param xmlNodeId 元素ID屬性值 

     * @return 删除元素後的xml文檔 

    public static String removeElementById(String srcXml, String xmlNodeId) { 

            Element removeElement = docSrc.getRootElement().elementByID(xmlNodeId); 

            removeElement.detach();  //直接删除自己 

//            removeElement.getParent().remove(removeElement);  //從父節點删除子節點 

            log.error("删除文檔中ID為" + xmlNodeId + "的節點發生異常,請檢查!"); 

     * 删除xml文檔中以xpath為直接父節點的ID屬性為空的子節點,ID屬性為空包括值為空、空串、或者ID屬性不存在。 

     * @param srcXml 原xml文檔 

     * @param xpath  要删除空節點的所在父節點的xpath 

     * @return 删除空節點後的xml文檔 

    public static String removeNullIdElement(String srcXml, String xpath) { 

            Document srcDoc = DocumentHelper.parseText(srcXml); 

            removeNullIdElement(srcDoc, xpath); 

            resultXml = srcDoc.asXML(); 

            log.error("在" + xpath + "下删除空節點發生異常,請檢查xpath是否正确!"); 

     * @param srcDoc 原xml的Document對象 

    public static Document removeNullIdElement(Document srcDoc, String xpath) { 

        Node parentNode = srcDoc.getRootElement().selectSingleNode(xpath); 

        if (!(parentNode instanceof Element)) { 

            log.error("所傳入的xpath不是Elementpath,删除空節點失敗!"); 

        } else { 

            int i = 0; 

            for (Iterator<Element> it = ((Element) parentNode).elementIterator(); it.hasNext();) { 

                Element element = it.next(); 

                if (element.attribute("ID") == null) { 

                    element.detach(); 

                    i++; 

                } else { 

                    if (StringUtils.isBlank(element.attribute("ID").getValue())) {             

                            element.detach(); 

                            i++;

                     }

                } 

            } 

            log.info("在" + xpath + "下成功删除" + i + "了個空節點!"); 

        return srcDoc; 

     * 删除xml文檔中指定xpath路徑下所有直接子節點為空的節點 

     * @param srcXml    原xml文檔 

     * @param xpathList xpaht清單 

    public static String removeAllNullIdElement(String srcXml, ArrayList<String> xpathList) { 

            for (Iterator<String> it = xpathList.iterator(); it.hasNext();) { 

                String xpath = it.next(); 

                removeNullIdElement(srcDoc, xpath); 

     * 更新xml文檔中指定ID的元素,ID保持不變 

     * @param srcXml     原xml 

     * @param newNodeXml 新xml節點 

     * @param xmlNodeId  更新元素ID屬性值 

     * @return 更新元素後的xml文檔 

    public static String updateElementById(String srcXml, String newNodeXml, String xmlNodeId) { 

            Document newDocNode = DocumentHelper.parseText(newNodeXml); 

            //擷取要更新的目标節點 

            Element updatedNode = docSrc.elementByID(xmlNodeId); 

            //擷取更新目标節點的父節點 

            Element parentUpNode = updatedNode.getParent(); 

            //删除掉要更新的節點 

            parentUpNode.remove(updatedNode); 

            //擷取新節點的根節點(作為寫入節點) 

            Element newRoot = newDocNode.getRootElement(); 

            //處理新節點的ID屬性值和BS子元素的值 

            if (newRoot.attribute("ID") == null) { 

                newRoot.addAttribute("ID", xmlNodeId); 

            } else { 

                newRoot.attribute("ID").setValue(xmlNodeId); 

            //在原文檔中更新位置寫入新節點 

            parentUpNode.add(newRoot); 

            log.error("更新xml文檔中ID為" + xmlNodeId + "節點發生異常,請檢查!"); 

     * 更新xml文檔中指定ID的元素,并檢查ID和BS,加以設定 

    public static String updateElementByIdAddIdBs(String srcXml, String newNodeXml, String xmlNodeId) { 

            if (newRoot.element("BS") == null) { 

                newRoot.addElement("BS", xmlNodeId); 

                newRoot.element("BS").setText(xmlNodeId); 

     * 為xml元素設定ID屬性 

     * @param xmlElement 原xml元素 

     * @return 設定id後的xml串 

    public static String addIdAttribute(String xmlElement) { 

            Document srcDoc = DocumentHelper.parseText(xmlElement); 

            Element root = srcDoc.getRootElement(); 

//            Long nextValue = SequenceUtils.getSequeceNextValue(); 

            Long nextValue = new Random().nextLong(); 

            root.addAttribute("ID", nextValue.toString()); 

            resultXml = root.asXML(); 

            log.error("給xml元素設定ID屬性發生異常,請檢查!"); 

     * 為xml元素設定ID屬性,并将此屬性寫入一個指定子節點文本值域 

     * @param nodeName   (直接)子節點的名稱,或相對目前節點的xpath路徑 

     * @return 設定id和子節點後的xml串 

    public static String addIdAndWriteNode(String xmlElement, String nodeName) { 

            Node bsElement = root.selectSingleNode(nodeName); 

            if (bsElement instanceof Element && bsElement != null) { 

                bsElement.setText(nextValue.toString()); 

                root.addElement(nodeName).setText(nextValue.toString()); 

            log.error("給xml元素設定ID屬性和直接" + nodeName + "子元素值時發生異常,請檢查!"); 

    public static void main(String args[]) { 

        test(); 

    public static void test() { 

        System.out.println("----------test()----------"); 

        String srcXml = "<?xml version=\"1.0\" encoding=\"GBK\"?>\n" + 

                "<doc>\n" + 

                "    <person>\n" + 

                "        <name>某人</name>\n" + 

                "        <adds>\n" + 

                "            <add ID=\"10001\">\n" + 

                "                <BS>10001</BS>\n" + 

                "                <note>鄭州市經三路</note>\n" + 

                "            </add>\n" + 

                "            <add ID=\"10002\">\n" + 

                "                <BS>10002</BS>\n" + 

                "                <note>西安市太白路</note>\n" + 

                "            <add ID=\"\">\n" + 

                "                <note>空ID節點啊</note>\n" + 

                "            <add>\n" + 

                "        </adds>\n" + 

                "    </person>\n" + 

                "    <other>\n" + 

                "        <name ID=\"HEHE\">ASDF</name>\n" + 

                "        <name>空ID節點啊</name>\n" + 

                "    </other>\n" + 

                "</doc>"; 

        String nodeXml1 = "            <add >\n" + 

                "                <BS></BS>\n" + 

                "                <note>西安市太白路1</note>\n" + 

                "            </add>"; 

        String nodeXml2 = "            <add>\n" + 

                "                <note>西安市太白路2</note>\n" + 

//        System.out.println("輸出三個測試對象"); 

//        System.out.println("----------srcXml------------"); 

//        System.out.println(srcXml); 

//        System.out.println("----------nodeXml1------------"); 

//        System.out.println("----------nodeXml2------------"); 

        System.out.println("----------addElement()測試----------"); 

        String addrs = addElement(srcXml, nodeXml1, "/doc/person/adds"); 

        System.out.println(addrs); 

        System.out.println("----------addIdAttribute()測試----------"); 

        String addIdrs = addIdAttribute(nodeXml1); 

        System.out.println(addIdrs); 

        System.out.println("----------addIdAndWriteNode()測試----------"); 

        String addIdNoders = addIdAndWriteNode(nodeXml1, "BS"); 

        System.out.println(addIdNoders); 

        System.out.println("----------removeElementById()測試----------"); 

        String removeIdrs = removeElementById(srcXml, "10001"); 

        System.out.println(removeIdrs); 

        System.out.println("----------updateElementByIdAddIdBs()測試----------"); 

        String upbyidrs = updateElementByIdAddIdBs(srcXml, nodeXml2, "10001"); 

        System.out.println(upbyidrs); 

        System.out.println("----------updateElementById()測試----------"); 

        String upbyidrs1 = updateElementById(srcXml, nodeXml2, "10001"); 

        System.out.println(upbyidrs1); 

        System.out.println("----------removeNullIdElement()測試----------"); 

        String rvnullrs = removeNullIdElement(srcXml, "/doc/person/adds"); 

        System.out.println(rvnullrs); 

        System.out.println("----------removeAllNullIdElement()測試----------"); 

        ArrayList<String> xpathList = new ArrayList<String>(); 

        xpathList.add("/doc/person/adds"); 

        xpathList.add("/doc/other"); 

        String rvallnullrs = removeAllNullIdElement(srcXml, xpathList); 

        System.out.println(rvallnullrs); 

        System.out.println("----------Dom4j生成一個xml測試----------"); 

        Document doc = DocumentHelper.createDocument(); 

        doc.addElement("root") 

                .addElement("person").setText("haha:)"); 

        System.out.println(doc.asXML()); 

}

運作結果:

----------test()---------- 

----------addElement()測試---------- 

<?xml version="1.0" encoding="GBK"?> 

            <add ID="10001"> 

            <add ID="10002"> 

            <add ID=""> 

        <add> 

                <BS/> 

                <note>西安市太白路1</note> 

            </add></adds> 

        <name ID="HEHE">ASDF</name> 

----------addIdAttribute()測試---------- 

<add ID="7549173897283584063"> 

----------addIdAndWriteNode()測試---------- 

<add ID="8974292836389323633"> 

                <BS>8974292836389323633</BS> 

----------removeElementById()測試---------- 

----------updateElementByIdAddIdBs()測試---------- 

        <add ID="10001"> 

                <note>西安市太白路2</note> 

            <BS xmlns="10001"/></add></adds> 

----------updateElementById()測試---------- 

----------removeNullIdElement()測試---------- 

16:17:32,689  INFO XmlNodeHandler:113 - 在/doc/person/adds下成功删除4了個空節點! 

----------removeAllNullIdElement()測試---------- 

16:17:32,705  INFO XmlNodeHandler:113 - 在/doc/person/adds下成功删除4了個空節點! 

16:17:32,705  INFO XmlNodeHandler:113 - 在/doc/other下成功删除3了個空節點! 

----------Dom4j生成一個xml測試---------- 

<?xml version="1.0" encoding="UTF-8"?> 

<root><person>haha:)</person></root> 

Process finished with exit code 0 

程式中盡量避免用Dom4j之外的第三方類庫,但是還用到了,可以修改一下: 

1、用到Log4j的地方,可以修改log對象的實作為Java中的Logger工具: 

      private static Logger log = Logger.getLogger(XmlNodeHandler.class.getName()); 

2、用到apache的beanutils工具包中的StringUtils.isBlank()方法時候,可以改用JDK API String中的equel()方法做比較進行替換。具體操作很簡單,我就不寫了。 

3、用到Sequence生成的Id的地方,我都改為java.util.Random類來實作,目的還是為了把眼光放到Dom的處理上。如果有博友對這個SequenceUtils工具類有興趣,我可以把代碼貼出去。 

本處理器工具類涵蓋Dom4j最常用部分80%以上的API。放到以友善檢視。 

衷心祝福廣大支援和浏覽熔岩部落格的朋友們:周末愉快!!! 

在最後奉獻出我親手制作的CHM格式的“Dom4j-1.6.1 API文檔”。

本文轉自 leizhimin 51CTO部落格,原文連結:http://blog.51cto.com/lavasoft/68558,如需轉載請自行聯系原作者