Dom4j 使用簡介

Dom4j  使用簡介
做者:冰雲 icecloud(AT)sina.com
時間:2003.12.15
 
版權聲明:
本文由冰雲完成,首發於CSDN,未經許可,不得使用於任何商業用途。
文中代碼部分引用自DOM4J文檔。
歡迎轉載,但請保持文章及版權聲明完整。
如需聯絡請發郵件:icecloud(AT)sina.com
 
    DOM4J是dom4j.org出品的一個開源XML解析包,它的網站中這樣定義:
Dom4j is an easy to use, open source library for working with XML, XPath and XSLT on the Java platform using the Java Collections Framework and with full support for DOM, SAX and JAXP.
Dom4j 是一個易用的、開源的庫,用於 XML XPath XSLT 。它應用於 Java 平臺,採用了 Java 集合框架並徹底支持 DOM SAX JAXP
DOM4J使用起來很是簡單。只要你瞭解基本的XML-DOM模型,就能使用。然而他本身帶的指南只有短短一頁(html),不過說的到挺全。國內的中文資料不多。於是俺寫這個短小的教程方便你們使用,這篇文章僅談及基本的用法,如需深刻的使用,請……本身摸索或查找別的資料。
以前看過IBM developer社區的文章(參見附錄),提到一些XML解析包的性能比較,其中DOM4J的性能很是出色,在多項測試中名列前茅。(事實上DOM4J的官方文檔中也引用了這個比較)因此此次的項目中我採用了DOM4J做爲XML解析工具。
在國內比較流行的是使用JDOM做爲解析器,二者各擅其長,但DOM4J最大的特點是使用大量的接口,這也是它被認爲比JDOM靈活的主要緣由。大師不是說過麼,「面向接口編程」。目前使用DOM4J的已經愈來愈多。若是你善於使用JDOM,不妨繼續用下去,只看看本篇文章做爲了解與比較,若是你正要採用一種解析器,不如就用DOM4J吧。
它的主要接口都在org.dom4j這個包裏定義:
Attribute定義了XML的屬性
Branch爲可以包含子節點的節點如XML元素(Element)和文檔(Docuemnts)定義了一個公共的行爲,
CDATA 定義了XML CDATA 區域
CharacterData是一個標識藉口,標識基於字符的節點。如CDATA,Comment, Text.
Comment 定義了XML註釋的行爲
定義了XML文檔
DocumentType 定義XML DOCTYPE聲明
Element定義XML 元素
ElementHandler定義了 Element 對象的處理器
被  ElementHandler 使用,用於取得當前正在處理的路徑層次信息
Entity定義 XML entity
Node爲全部的dom4j中XML節點定義了多態行爲
NodeFilter 定義了在dom4j節點中產生的一個濾鏡或謂詞的行爲(predicate)
ProcessingInstruction 定義 XML 處理指令.
Text 定義XML 文本節點.
Visitor 用於實現Visitor模式.
XPath 在分析一個字符串後會提供一個XPath 表達式
看名字大體就知道它們的涵義如何了。
要想弄懂這套接口,關鍵的是要明白接口的繼承關係:
一目瞭然,不少事情都清楚了。大部分都是由Node繼承來的。知道這些關係,未來寫程序就不會出現ClassCastException了。
下面給出一些例子(部分摘自DOM4J自帶的文檔),簡單說一下如何使用。
1.              讀取並解析XML文檔:
讀寫XML文檔主要依賴於org.dom4j.io包,其中提供 DOMReader和SAXReader兩類不一樣方式,而調用方式是同樣的。這就是依靠接口的好處。
 
    // 從文件讀取XML,輸入文件名,返回XML文檔
     public Document read(String fileName)  throws MalformedURLException, DocumentException {
       SAXReader reader =  new SAXReader();
       Document document = reader.read( new File(fileName));
        return document;
    }
 
其中,reader的read方法是重載的,能夠從InputStream, File, Url等多種不一樣的源來讀取。獲得的Document對象就帶表了整個XML。
根據本人本身的經驗,讀取的字符編碼是按照XML文件頭定義的編碼來轉換。若是遇到亂碼問題,注意要把各處的編碼名稱保持一致便可。
2.    取得Root節點
讀取後的第二步,就是獲得Root節點。熟悉XML的人都知道,一切XML分析都是從Root元素開始的。
 
    public Element getRootElement(Document doc){
        return doc.getRootElement();
    }
 
3.    遍歷XML樹
DOM4J提供至少3種遍歷節點的方法:
1) 枚舉(Iterator)
 
    // 枚舉全部子節點
    for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
       Element element = (Element) i.next();
       // do something
    }
    // 枚舉名稱爲foo的節點
    for ( Iterator i = root.elementIterator(foo); i.hasNext();) {
       Element foo = (Element) i.next();
       // do something
    }
    // 枚舉屬性
    for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
       Attribute attribute = (Attribute) i.next();
       // do something
    }
2)遞歸
遞歸也能夠採用Iterator做爲枚舉手段,但文檔中提供了另外的作法
 
     public  void treeWalk() {
       treeWalk(getRootElement());
    }
     public  void treeWalk(Element element) {
        for ( int i = 0, size = element.nodeCount(); i < size; i++)     {
           Node node = element.node(i);
            if (node  instanceof Element) {
              treeWalk((Element) node);
           }  else { // do something....
           }
       }
}
 
3) Visitor模式
最使人興奮的是DOM4J對Visitor的支持,這樣能夠大大縮減代碼量,而且清楚易懂。瞭解設計模式的人都知道,Visitor是GOF設計模式之一。其主要原理就是兩種類互相保有對方的引用,而且一種做爲Visitor去訪問許多Visitable。咱們來看DOM4J中的Visitor模式(快速文檔中沒有提供)
只須要自定一個類實現Visitor接口便可。
 
         public  class MyVisitor  extends VisitorSupport {
            public  void visit(Element element){
               System.out.println(element.getName());
           }
           public  void visit(Attribute attr){
               System.out.println(attr.getName());
           }
        }
 
        調用:  root.accept(new MyVisitor())
    Visitor接口提供多種Visit()的重載,根據XML不一樣的對象,將採用不一樣的方式來訪問。上面是給出的Element和Attribute的簡單實現,通常比較經常使用的就是這兩個。VisitorSupport是DOM4J提供的默認適配器,Visitor接口的Default Adapter模式,這個模式給出了各類visit(*)的空實現,以便簡化代碼。
    注意,這個Visitor是自動遍歷全部子節點的。若是是root.accept(MyVisitor),將遍歷子節點。我第一次用的時候,認爲是須要本身遍歷,便在遞歸中調用Visitor,結果可想而知。
4. XPath支持
    DOM4J對XPath有良好的支持,如訪問一個節點,可直接用XPath選擇。
 
    public  void bar(Document document) {
        List list = document.selectNodes( //foo/bar );
        Node node = document.selectSingleNode(//foo/bar/author);
        String name = node.valueOf( @name );
     }
 
    例如,若是你想查找XHTML文檔中全部的超連接,下面的代碼能夠實現:
 
     public  void findLinks(Document document)  throws DocumentException {
        List list = document.selectNodes( //a/@href );
         for (Iterator iter = list.iterator(); iter.hasNext(); ) {
            Attribute attribute = (Attribute) iter.next();
            String url = attribute.getValue();
        }
     }
 
5. 字符串與XML的轉換
有時候常常要用到字符串轉換爲XML或反之,
 
    // XML轉字符串
  Document document = ...;
    String text = document.asXML();
// 字符串轉XML
    String text = James ;
    Document document = DocumentHelper.parseText(text);
 
6 用XSLT轉換XML
 
    public Document styleDocument(
       Document document,
       String stylesheet
    )  throws Exception {
    // load the transformer using JAXP
    TransformerFactory factory = TransformerFactory.newInstance();
    Transformer transformer = factory.newTransformer(
        new StreamSource( stylesheet )
    );
    // now lets style the given document
    DocumentSource source =  new DocumentSource( document );
    DocumentResult result =  new DocumentResult();
    transformer.transform( source, result );
    // return the transformed document
    Document transformedDoc = result.getDocument();
     return transformedDoc;
}
 
7. 建立XML
  通常建立XML是寫文件前的工做,這就像StringBuffer同樣容易。
 
     public Document createDocument() {
       Document document = DocumentHelper.createDocument();
       Element root = document.addElement(root);
       Element author1 =
           root
              .addElement(author)
              .addAttribute(name, James)
              .addAttribute(location, UK)
              .addText(James Strachan);
       Element author2 =
           root
              .addElement(author)
              .addAttribute(name, Bob)
              .addAttribute(location, US)
              .addText(Bob McWhirter);
        return document;
    }
 
8. 文件輸出
    一個簡單的輸出方法是將一個Document或任何的Node經過write方法輸出
 
    FileWriter out =  new FileWriter( foo.xml );
    document.write(out);
 
  若是你想改變輸出的格式,好比美化輸出或縮減格式,能夠用XMLWriter類
 
     public  void write(Document document)  throws IOException {
       // 指定文件
       XMLWriter writer =  new XMLWriter(
            new FileWriter( output.xml )
       );
       writer.write( document );
       writer.close();
       // 美化格式
       OutputFormat format = OutputFormat.createPrettyPrint();
       writer =  new XMLWriter( System.out, format );
       writer.write( document );
       // 縮減格式
       format = OutputFormat.createCompactFormat();
       writer =  new XMLWriter( System.out, format );
       writer.write( document );
    }
 
如何,DOM4J夠簡單吧,固然,還有一些複雜的應用沒有提到,如ElementHandler等。若是你動心了,那就一塊兒來用DOM4J.
DOM4J官方網站:(我老連不上)
DOM4J下載(SourceForge),最新版本爲1.4
發表於 2004年9月27日 20:21
本文主要討論了用dom4j解析XML的基礎問題,包括創建XML文檔,添加、修改、刪除節點,以及格式化(美化)輸出和中文問題。可做爲dom4j的入門資料。
轉載自:http://jalorsoft.com/holen/
做者:陳光( holen@263.net
時間:2004-09-11
 
本文主要討論了用dom4j解析XML的基礎問題,包括創建XML文檔,添加、修改、刪除節點,以及格式化(美化)輸出和中文問題。可做爲dom4j的入門資料。
 
1   下載與安裝
 
dom4j是sourceforge.net上的一個開源項目,主要用於對XML的解析。從2001年7月發佈初版以來,已陸續推出多個版本,目前最高版本爲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"?>
 
    <!--This is a test for dom4j, holen, 2004.9.11-->
   
      
   
   
      
   
   
      
   
    O'Reilly
 
 
這是一個很簡單的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"?>
<!--This is a test for dom4j, holen, 2004.9.11-->O'Reilly
 
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</
相關文章
相關標籤/搜索