DOM4J

從 华夏文化百科
跳到: 導覽搜尋

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這個包里定義:AttributeAttribute定義了XML的屬性BranchBranch為能夠包含子節點的節點如XML元素(Element)和文檔(Docuemnts)定義了一個公共的行為,CDATACDATA 定義了XML CDATA 區域CharacterDataCharacterData是一個標識藉口,標識基於字符的節點。如CDATA,Comment, Text.CommentComment 定義了XML注釋的行為Document定義了XML文檔DocumentTypeDocumentType 定義XML DOCTYPE聲明ElementElement定義XML 元素ElementHandlerElementHandler定義了 Element 對象的處理器ElementPath被 ElementHandler 使用,用於取得當前正在處理的路徑層次信息EntityEntity定義 XML entityNodeNode為所有的dom4j中XML節點定義了多態行為NodeFilterNodeFilter 定義了在dom4j節點中產生的一個濾鏡或謂詞的行為(predicate)ProcessingInstructionProcessingInstruction 定義 XML 處理指令.TextText 定義XML 文本節點.VisitorVisitor 用於實現Visitor模式.XPathXPath 在分析一個字符串後會提供一個XPath 表達式看名字大致就知道它們的涵義如何了。要想弄懂這套接口,關鍵的是要明白接口的繼承關係: * interface java.lang.Cloneableo interface org.dom4j.Node+ interface org.dom4j.Attribute+ interface org.dom4j.Branch# interface org.dom4j.Document# interface org.dom4j.Element+ interface org.dom4j.CharacterData# interface org.dom4j.CDATA# interface org.dom4j.Comment# interface org.dom4j.Text+ interface org.dom4j.DocumentType+ interface org.dom4j.Entity+ interface org.dom4j.ProcessingInstruction一目了然,很多事情都清楚了。大部分都是由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官方網站:(我老連不上)[url]http://www.dom4j.org[/url]DOM4J下載(SourceForge),最新版本為1.4[url]http://sourceforge.net/projects/dom4j[/url]參考資料:DOM4J文檔Java 中的 XML:文檔模型,第一部分:性能[url]http://www-900.ibm.com/developerWorks/cn/xml/x-injava/index.shtml[/url]Java 中的 XML:Java 文檔模型的用法[url]http://www-900.ibm.com/developerWorks/cn/xml/x-injava2/index.shtml[/url]