Dom4j解析和生成XML文檔

原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本人聲明。否則將追究法律責任。
作者:永恆の_☆ 地址:http://blog.csdn.net/chenghui0317/article/details/11486271

原文

一、前言

    dom4j是一套非常優秀的Java開源api,主要用於讀寫xml文檔,具有性能優異、功能強大、和非常方便使用的特點。   另外xml經常用於數據交換的載體,像調用webservice傳遞的參數,以及數據做同步操作等等,   所以使用dom4j解析xml是非常有必要的。


二、準備條件

   dom4j.jar

下載地址:http://sourceforge.net/projects/dom4j/


三、使用Dom4j實戰


1、解析xml文檔

實現思路:

   <1>根據讀取的xml路徑,傳遞給SAXReader之後 返回一個Document文檔對象;

   <2>然後操作這個Document對象,獲取下面的節點以及子節點的信息;

具體代碼如下:

[java] view plain copy
 print?
  1. import java.io.File;  
  2. import java.io.FileInputStream;  
  3. import java.io.InputStream;  
  4. import java.util.Iterator;  
  5. import java.util.List;  
  6.   
  7. import org.dom4j.Document;  
  8. import org.dom4j.DocumentHelper;  
  9. import org.dom4j.Element;  
  10. import org.dom4j.io.SAXReader;  
  11.   
  12. /** 
  13.  * 使用dom4j解析xml文檔 
  14.  * @author Administrator 
  15.  * 
  16.  */  
  17. public class Dom4jParseXmlDemo {  
  18.       
  19.     public void parseXml01(){  
  20.         try{  
  21.             //將src下面的xml轉換爲輸入流  
  22.             InputStream inputStream = new FileInputStream(new File("D:/project/dynamicWeb/src/resource/module01.xml"));   
  23.             //InputStream inputStream = this.getClass().getResourceAsStream("/module01.xml");//也可以根據類的編譯文件相對路徑去找xml  
  24.             //創建SAXReader讀取器,專門用於讀取xml  
  25.             SAXReader saxReader = new SAXReader();  
  26.             //根據saxReader的read重寫方法可知,既可以通過inputStream輸入流來讀取,也可以通過file對象來讀取   
  27.             //Document document = saxReader.read(inputStream);    
  28.             Document document = saxReader.read(new File("D:/project/dynamicWeb/src/resource/module01.xml"));//必須指定文件的絕對路徑  
  29.             //另外還可以使用DocumentHelper提供的xml轉換器也是可以的。  
  30.             //Document document = DocumentHelper.parseText("<?xml version=\"1.0\" encoding=\"UTF-8\"?><modules id=\"123\"><module> 這個是module標籤的文本信息</module></modules>");  
  31.               
  32.             //獲取根節點對象  
  33.             Element rootElement = document.getRootElement();    
  34.             System.out.println("根節點名稱:" + rootElement.getName());//獲取節點的名稱  
  35.             System.out.println("根節點有多少屬性:" + rootElement.attributeCount());//獲取節點屬性數目  
  36.             System.out.println("根節點id屬性的值:" + rootElement.attributeValue("id"));//獲取節點的屬性id的值  
  37.             System.out.println("根節點內文本:" + rootElement.getText());//如果元素有子節點則返回空字符串,否則返回節點內的文本  
  38.             //rootElement.getText() 之所以會換行是因爲 標籤與標籤之間使用了tab鍵和換行符佈局,這個也算是文本所以顯示出來換行的效果。  
  39.             System.out.println("根節點內文本(1):" + rootElement.getTextTrim());//去掉的是標籤與標籤之間的tab鍵和換行符等等,不是內容前後的空格  
  40.             System.out.println("根節點子節點文本內容:" + rootElement.getStringValue()); //返回當前節點遞歸所有子節點的文本信息。  
  41.               
  42.             //獲取子節點  
  43.             Element element = rootElement.element("module");  
  44.             if(element != null){  
  45.                 System.out.println("子節點的文本:" + element.getText());//因爲子節點和根節點都是Element對象所以它們的操作方式都是相同的  
  46.             }  
  47.             //但是有些情況xml比較複雜,規範不統一,某個節點不存在直接java.lang.NullPointerException,所以獲取到element對象之後要先判斷一下是否爲空  
  48.               
  49.             rootElement.setName("root");//支持修改節點名稱  
  50.             System.out.println("根節點修改之後的名稱:" + rootElement.getName());  
  51.             rootElement.setText("text"); //同樣修改標籤內的文本也一樣  
  52.             System.out.println("根節點修改之後的文本:" + rootElement.getText());  
  53.         } catch (Exception e) {    
  54.             e.printStackTrace();    
  55.         }    
  56.     }  
  57.       
  58.     public static void main(String[] args) {  
  59.         Dom4jParseXmlDemo demo = new Dom4jParseXmlDemo();  
  60.         demo.parseXml01();  
  61.     }  
  62. }  
另外上面的xml在src下面,module01.xml具體如下:

[html] view plain copy
 print?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <modules id="123">  
  3.     <module> 這個是module標籤的文本信息</module>  
  4. </modules>  
接下來執行該類的main方法,console效果如下:

由此以知: 

   <1>dom4j讀取xml文件方式有很多樣;

   <2>取出element對象的文本和標籤名稱都非常簡單;

   <3>並且修改元素的文本和標籤名稱都非常方便,但是不會寫入到磁盤xml文件中。


上面只是簡單的獲取了xml的根目錄的元素,接下來使用Iterator 迭代器循環document文檔對象。

具體代碼如下:

[java] view plain copy
 print?
  1. public void parseXml02(){  
  2.     try{  
  3.         //將src下面的xml轉換爲輸入流  
  4.         InputStream inputStream = this.getClass().getResourceAsStream("/module02.xml");  
  5.         //創建SAXReader讀取器,專門用於讀取xml  
  6.            SAXReader saxReader = new SAXReader();  
  7.            //根據saxReader的read重寫方法可知,既可以通過inputStream輸入流來讀取,也可以通過file對象來讀取  
  8.            Document document = saxReader.read(inputStream);  
  9.              
  10.            Element rootElement = document.getRootElement();  
  11.         Iterator<Element> modulesIterator = rootElement.elements("module").iterator();  
  12.         //rootElement.element("name");獲取某一個子元素  
  13.         //rootElement.elements("name");獲取根節點下子元素moudule節點的集合,返回List集合類型  
  14.         //rootElement.elements("module").iterator();把返回的list集合裏面每一個元素迭代子節點,全部返回到一個Iterator集合中  
  15.         while(modulesIterator.hasNext()){  
  16.             Element moduleElement = modulesIterator.next();  
  17.             Element nameElement = moduleElement.element("name");  
  18.             System.out.println(nameElement.getName() + ":" + nameElement.getText());  
  19.             Element valueElement = moduleElement.element("value");  
  20.             System.out.println(valueElement.getName() + ":" + valueElement.getText());  
  21.             Element descriptElement = moduleElement.element("descript");  
  22.             System.out.println(descriptElement.getName() + ":" + descriptElement.getText());  
  23.         }     
  24.     } catch (Exception e) {    
  25.            e.printStackTrace();    
  26.        }    
  27. }     
另外上面的xml在src下面,module02.xml具體如下:
[html] view plain copy
 print?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <modules id="123">  
  3.     <module>      
  4.         <name>oa</name>  
  5.         <value>系統基本配置</value>  
  6.         <descript>對系統的基本配置根目錄</descript>  
  7.     </module>  
  8. </modules>  
接下來執行該類的main方法,console效果如下:

由此以知: 

   <1>dom4j迭代xml子元素非常的效率和便捷;


但是上面只是簡單的迭代了xml的子節點元素,但是如果xml規則比較複雜,比如接下來要測試的module03.xml,具體如下:

[html] view plain copy
 print?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <modules id="123">  
  3.      <module>這個是module標籤的文本信息</module>  
  4.     <module id="">  
  5.         <name>oa</name>  
  6.         <value>系統基本配置</value>  
  7.         <descript>對系統的基本配置根目錄</descript>  
  8.         <module>這個是子module標籤的文本信息</module>  
  9.     </module>  
  10.      <module>  
  11.         <name>管理配置</name>  
  12.         <value>none</value>  
  13.         <descript>管理配置的說明</descript>  
  14.         <module id="106">  
  15.             <name>系統管理</name>  
  16.             <value>0</value>  
  17.             <descript>Config</descript>  
  18.             <module id="107">  
  19.                 <name>部門編號</name>  
  20.                 <value>20394</value>  
  21.                 <descript>編號</descript>  
  22.             </module>  
  23.         </module>  
  24.     </module>  
  25. </modules>  
因爲他們的結構不一樣,直接迭代的話 會報錯:

java.lang.NullPointerException

所以這個時候需要小心使用了,每次都不能把元素直接放進去迭代。具體實現代碼如下:

[java] view plain copy
 print?
  1. public void parseXml03(){  
  2.     try{  
  3.         //將src下面的xml轉換爲輸入流  
  4.         InputStream inputStream = this.getClass().getResourceAsStream("/module03.xml");  
  5.         //創建SAXReader讀取器,專門用於讀取xml  
  6.            SAXReader saxReader = new SAXReader();  
  7.            //根據saxReader的read重寫方法可知,既可以通過inputStream輸入流來讀取,也可以通過file對象來讀取  
  8.            Document document = saxReader.read(inputStream);  
  9.              
  10.            Element rootElement = document.getRootElement();  
  11.            if(rootElement.elements("module") != null ){  
  12.             //因爲第一個module標籤只有內容沒有子節點,直接.iterator()就java.lang.NullPointerException了, 所以需要分開實現  
  13.             List<Element> elementList = rootElement.elements("module");  
  14.             for (Element element : elementList) {  
  15.                 if(!element.getTextTrim().equals("")){  
  16.                     System.out.println("【1】" + element.getTextTrim());  
  17.                 }else{  
  18.                     Element nameElement = element.element("name");  
  19.                     System.out.println("   【2】" + nameElement.getName() + ":" + nameElement.getText());  
  20.                     Element valueElement = element.element("value");  
  21.                     System.out.println("   【2】" + valueElement.getName() + ":" + valueElement.getText());  
  22.                     Element descriptElement = element.element("descript");  
  23.                     System.out.println("   【2】" + descriptElement.getName() + ":" + descriptElement.getText());  
  24.                       
  25.                     List<Element> subElementList = element.elements("module");  
  26.                     for (Element subElement : subElementList) {  
  27.                         if(!subElement.getTextTrim().equals("")){  
  28.                             System.out.println("      【3】" + subElement.getTextTrim());  
  29.                         }else{  
  30.                             Element subnameElement = subElement.element("name");  
  31.                             System.out.println("      【3】" + subnameElement.getName() + ":" + subnameElement.getText());  
  32.                             Element subvalueElement = subElement.element("value");  
  33.                             System.out.println("      【3】" + subvalueElement.getName() + ":" + subvalueElement.getText());  
  34.                             Element subdescriptElement = subElement.element("descript");  
  35.                             System.out.println("      【3】" + subdescriptElement.getName() + ":" + subdescriptElement.getText());  
  36.                         }  
  37.                     }  
  38.                 }  
  39.             }  
  40.            }  
  41.     } catch (Exception e) {    
  42.            e.printStackTrace();    
  43.        }    
  44. }  
接下來執行該類的main方法,console效果如下:


好了,這下可以解決迭代文檔出現空引用的情況了。

另外代碼其實可以重構一下,因爲循環裏面取出子元素的操作都是重複的,可以利用遞歸改善,但是可讀性會變差一點。


如果有些時候需要獲取xml中所有的文本信息,又或者別人傳遞的xml格式不規範,比如標籤內名稱大小寫,雖然xml不區分大小寫,但是必須成對出現,所以爲了避免這種情況,索性可以將全部的標籤名稱換爲大寫,具體代碼如下:

[java] view plain copy
 print?
  1. public static void main(String[] args) {  
  2.     String str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><modules id=\"123\"><module> 這個是module標籤的文本信息<name>oa</name><value>系統基本配置</value><descript>對系統的基本配置根目錄</descript></module></modules>";  
  3.     System.out.println(str.replaceAll("<[^<]*>""_"));   
  4.     Pattern pattern = Pattern.compile("<[^<]*>");  
  5.     Matcher matcher = pattern.matcher(str);  
  6.     while(matcher.find()){  
  7.         str = str.replaceAll(matcher.group(0), matcher.group(0).toUpperCase());  
  8.     }  
  9.     System.out.println(str);  
  10.        
  11. }  
運行之後效果圖如下:



2、生成xml文檔

dom4j能夠解析xml,同樣肯定能生成xml,而且使用起來更加簡單方便。

實現思路:

   <1>DocumentHelper提供了創建Document對象的方法;

   <2>操作這個Document對象,添加節點以及節點下的文本、名稱和屬性值;

   <3>然後利用XMLWriter寫入器把封裝的document對象寫入到磁盤中;

具體代碼如下:

[java] view plain copy
 print?
  1. import java.io.FileWriter;  
  2. import java.io.IOException;  
  3. import java.io.Writer;  
  4.   
  5. import org.dom4j.Document;  
  6. import org.dom4j.DocumentHelper;  
  7. import org.dom4j.Element;  
  8. import org.dom4j.io.XMLWriter;  
  9.   
  10. /** 
  11.  * 使用dom4j生成xml文檔 
  12.  * @author Administrator 
  13.  * 
  14.  */  
  15. public class Dom4jBuildXmlDemo {  
  16.     public void build01(){  
  17.         try {  
  18.             //DocumentHelper提供了創建Document對象的方法  
  19.             Document document = DocumentHelper.createDocument();  
  20.             //添加節點信息  
  21.             Element rootElement = document.addElement("modules");  
  22.             //這裏可以繼續添加子節點,也可以指定內容  
  23.             rootElement.setText("這個是module標籤的文本信息");  
  24.             Element element = rootElement.addElement("module");  
  25.               
  26.             Element nameElement = element.addElement("name");  
  27.             Element valueElement = element.addElement("value");  
  28.             Element descriptionElement = element.addElement("description");  
  29.             nameElement.setText("名稱");  
  30.             nameElement.addAttribute("language""java");//爲節點添加屬性值  
  31.             valueElement.setText("值");  
  32.             valueElement.addAttribute("language""c#");  
  33.             descriptionElement.setText("描述");  
  34.             descriptionElement.addAttribute("language""sql server");  
  35.             System.out.println(document.asXML()); //將document文檔對象直接轉換成字符串輸出  
  36.             Writer fileWriter = new FileWriter("c:\\module.xml");  
  37.             //dom4j提供了專門寫入文件的對象XMLWriter  
  38.             XMLWriter xmlWriter = new XMLWriter(fileWriter);  
  39.             xmlWriter.write(document);  
  40.             xmlWriter.flush();  
  41.             xmlWriter.close();  
  42.             System.out.println("xml文檔添加成功!");  
  43.         } catch (IOException e) {  
  44.             e.printStackTrace();  
  45.         }  
  46.     }  
  47.       
  48.     public static void main(String[] args) {  
  49.         Dom4jBuildXmlDemo demo = new Dom4jBuildXmlDemo();  
  50.         demo.build01();  
  51.     }  
  52. }  

運行代碼效果如下:


然後去c盤下面查看是否創建成功,結果發現在xml文件中的內容與控制檯輸出的內容一樣。

另外上面生成xml並沒有指定編碼格式,但是還是顯示了UTF-8,說明這個是默認的編碼格式,如果想重新指定可以在寫入到磁盤之前加上document.setXMLEncoding("GBK");就好了。

發佈了11 篇原創文章 · 獲贊 6 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章