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,如需轉載請自行聯系原作者