用Dom4j解析XML及中文問題

Dom4j解析XML及中文問題

本文主要討論了用dom4j解析XML的基礎問題,包括建立XML文檔,添加、修改、刪除節點,以及格式化(美化)輸出和中文問題。可作爲dom4j的入門資料。

 

1. 下載與安裝

 

dom4jsourceforge.net上的一個開源項目,主要用於對XML的解析。從20017月發佈第一版以來,已陸續推出多個版本,目前最高版本爲1.5

dom4j專門針對Java開發,使用起來非常簡單、直觀,在Java界,dom4j正迅速普及。

 

可以到http://sourceforge.net/projects/dom4j下載其最新版。

 

dom4j1.5的完整版大約13M,是一個名爲dom4j-1.5.zip的壓縮包,解壓後有一個dom4j-1.5.jar文件,這就是應用時需要引入的類包,另外還有一個jaxen-1.1-beta-4.jar文件,一般也需要引入,否則執行時可能拋java.lang.NoClassDefFoundError: org/jaxen/JaxenException異常,其他的包可以選擇用之。

 

2. 示例XML文檔(holen.xml

 

爲了述說方便,先看一個XML文檔,之後的操作均以此文檔爲基礎。

 

holen.xml

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

<books>

       <!--This is a test for dom4j, holen, 2004.9.11-->

       <book show="yes">

              <title>Dom4j Tutorials</title>

       </book>

       <book show="yes">

              <title>Lucene Studing</title>

       </book>

       <book show="no">

              <title>Lucene in Action</title>

       </book>

       <owner>O'Reilly</owner>

</books>

 

這是一個很簡單的XML文檔,場景是一個網上書店,有很多書,每本書有兩個屬性,一個是書名[title],一個爲是否展示[show],最後還有一項是這些書的擁有者[owner]信息。

 

3. 建立一個XML文檔

 

 

    /**

     * 建立一個XML文檔,文檔名由輸入屬性決定

     * @param filename 需建立的文件名

     * @return 返回操作結果, 0表失敗, 1表成功

     */

    public int createXMLFile(String filename){

       /** 返回操作結果, 0表失敗, 1表成功 */

       int returnValue = 0;

       /** 建立document對象 */

       Document document = DocumentHelper.createDocument();

       /** 建立XML文檔的根books */

       Element booksElement = document.addElement("books");

       /** 加入一行註釋 */

       booksElement.addComment("This is a test for dom4j, holen, 2004.9.11");

       /** 加入第一個book節點 */

       Element bookElement = booksElement.addElement("book");

       /** 加入show屬性內容 */

       bookElement.addAttribute("show","yes");

       /** 加入title節點 */

       Element titleElement = bookElement.addElement("title");

       /** title設置內容 */

       titleElement.setText("Dom4j Tutorials");

      

       /** 類似的完成後兩個book */

       bookElement = booksElement.addElement("book");

       bookElement.addAttribute("show","yes");

       titleElement = bookElement.addElement("title");

       titleElement.setText("Lucene Studing");

       bookElement = booksElement.addElement("book");

       bookElement.addAttribute("show","no");

       titleElement = bookElement.addElement("title");

       titleElement.setText("Lucene in Action");

      

       /** 加入owner節點 */

       Element ownerElement = booksElement.addElement("owner");

       ownerElement.setText("O'Reilly");

      

       try{

           /** document中的內容寫入文件中 */

           XMLWriter writer = new XMLWriter(new FileWriter(new File(filename)));

           writer.write(document);

           writer.close();

           /** 執行成功,需返回1 */

           returnValue = 1;

       }catch(Exception ex){

           ex.printStackTrace();

       }

             

       return returnValue;

    }

 

說明:

Document document = DocumentHelper.createDocument();

通過這句定義一個XML文檔對象。

 

Element booksElement = document.addElement("books");

通過這句定義一個XML元素,這裏添加的是根節點。

Element有幾個重要的方法:

l         addComment:添加註釋

l         addAttribute:添加屬性

l         addElement:添加子元素

 

最後通過XMLWriter生成物理文件,默認生成的XML文件排版格式比較亂,可以通過OutputFormat類的createCompactFormat()方法或createPrettyPrint()方法格式化輸出,默認採用createCompactFormat()方法,顯示比較緊湊,這點將在後面詳細談到。

 

生成後的holen.xml文件內容如下:

 

 

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

<books><!--This is a test for dom4j, holen, 2004.9.11--><book show="yes"><title>Dom4j Tutorials</title></book><book show="yes"><title>Lucene Studing</title></book><book show="no"><title>Lucene in Action</title></book><owner>O'Reilly</owner></books>

 

4. 修改XML文檔

 

有三項修改任務,依次爲:

l         如果book節點中show屬性的內容爲yes,則修改成no

l         owner項內容改爲Tshinghua,並添加date節點

l         title內容爲Dom4j Tutorials,則刪除該節點

 

 

    /**

     * 修改XML文件中內容,並另存爲一個新文件

     * 重點掌握dom4j中如何添加節點,修改節點,刪除節點

     * @param filename 修改對象文件

     * @param newfilename 修改後另存爲該文件

     * @return 返回操作結果, 0表失敗, 1表成功

     */

    public int ModiXMLFile(String filename,String newfilename){

       int returnValue = 0;

       try{

           SAXReader saxReader = new SAXReader();

           Document document = saxReader.read(new File(filename));

           /** 修改內容之一: 如果book節點中show屬性的內容爲yes,則修改成no */

           /** 先用xpath查找對象 */

           List list = document.selectNodes("/books/book/@show" );

           Iterator iter = list.iterator();

           while(iter.hasNext()){

              Attribute attribute = (Attribute)iter.next();

              if(attribute.getValue().equals("yes")){

                  attribute.setValue("no");

              }  

           }

          

           /**

            * 修改內容之二: owner項內容改爲Tshinghua

            * 並在owner節點中加入date節點,date節點的內容爲2004-09-11,還爲date節點添加一個屬性type

            */

           list = document.selectNodes("/books/owner" );

           iter = list.iterator();

           if(iter.hasNext()){

              Element ownerElement = (Element)iter.next();

              ownerElement.setText("Tshinghua");

              Element dateElement = ownerElement.addElement("date");

              dateElement.setText("2004-09-11");

              dateElement.addAttribute("type","Gregorian calendar");

           }

          

           /** 修改內容之三: title內容爲Dom4j Tutorials,則刪除該節點 */

           list = document.selectNodes("/books/book");

           iter = list.iterator();

           while(iter.hasNext()){

              Element bookElement = (Element)iter.next();

              Iterator iterator = bookElement.elementIterator("title");

               while(iterator.hasNext()){

                  Element titleElement=(Element)iterator.next();

                  if(titleElement.getText().equals("Dom4j Tutorials")){

                     bookElement.remove(titleElement);

                  }

              }

           }         

          

           try{

              /** document中的內容寫入文件中 */

              XMLWriter writer = new XMLWriter(new FileWriter(new File(newfilename)));

              writer.write(document);

              writer.close();

              /** 執行成功,需返回1 */

              returnValue = 1;

           }catch(Exception ex){

              ex.printStackTrace();

           }

          

       }catch(Exception ex){

           ex.printStackTrace();

       }

       return returnValue;

    }

   

 

說明:

List list = document.selectNodes("/books/book/@show" );

list = document.selectNodes("/books/book");

上述代碼通過xpath查找到相應內容。

 

通過setValue()setText()修改節點內容。

 

通過remove()刪除節點或屬性。

 

5. 格式化輸出和指定編碼

 

默認的輸出方式爲緊湊方式,默認編碼爲UTF-8,但對於我們的應用而言,一般都要用到中文,並且希望顯示時按自動縮進的方式的顯示,這就需用到OutputFormat類。

 

 

   

    /**

     * 格式化XML文檔,並解決中文問題

     * @param filename

     * @return

     */

    public int formatXMLFile(String filename){

       int returnValue = 0;

       try{

           SAXReader saxReader = new SAXReader();

           Document document = saxReader.read(new File(filename));

           XMLWriter writer = null;

           /** 格式化輸出,類型IE瀏覽一樣 */

           OutputFormat format = OutputFormat.createPrettyPrint();

           /** 指定XML編碼 */

           format.setEncoding("GBK");

           writer= new XMLWriter(new FileWriter(new File(filename)),format);

           writer.write(document);

           writer.close();     

           /** 執行成功,需返回1 */

           returnValue = 1;    

       }catch(Exception ex){

           ex.printStackTrace();

       }

       return returnValue;

    }

 

說明:

 

OutputFormat format = OutputFormat.createPrettyPrint();

這句指定了格式化的方式爲縮進式,則非緊湊式。

 

format.setEncoding("GBK");

指定編碼爲GBK

 

XMLWriter writer = new XMLWriter(new FileWriter(new File(filename)),format);

這與前面兩個方法相比,多加了一個OutputFormat對象,用於指定顯示和編碼方式。

 

6. 完整的類代碼

 

前面提出的方法都是零散的,下面給出完整類代碼。

 

Dom4jDemo.java

package com.holen.dom4j;

 

import java.io.File;

import java.io.FileWriter;

import java.util.Iterator;

import java.util.List;

 

import org.dom4j.Attribute;

import org.dom4j.Document;

import org.dom4j.DocumentHelper;

import org.dom4j.Element;

import org.dom4j.io.OutputFormat;

import org.dom4j.io.SAXReader;

import org.dom4j.io.XMLWriter;

 

/**

 * @author Holen Chen

 */

public class Dom4jDemo {

   

    public Dom4jDemo() {

    }

 

    public int createXMLFile(String filename){…}

    public int ModiXMLFile(String filename,String newfilename){…}

    public int formatXMLFile(String filename){…}

 

    public static void main(String[] args) {

       Dom4jDemo temp = new Dom4jDemo();

       System.out.println(temp.createXMLFile("d://holen.xml"));        System.out.println(temp.ModiXMLFile("d://holen.xml","d://holen2.xml"));

       System.out.println(temp.formatXMLFile("d://holen2.xml"));

    }

}

 

說明:

main()方法中依次調用三個方法,第一個方法用於生成holen.xml,第二個方法用於修改holen.xml,並且修改後的內容另存爲holen2.xml,第三個方法將holen2.xml格式化縮進式輸出,並指定編碼方式爲GBK

 

重新格式化後holen2.xml文件顯示如下:

項目視圖供參考:

7. 總結

總的來說,dom4j的使用是很簡單的,而且與Java結合緊密,功能強大。

 

參考資料

1.  dom4j文檔

2.  使用 dom4j 解析 XMLDeepak VohradeveloperWorks

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章