簡介:Jdom是用Java語言讀、寫、操作XML的新API函數(shù)。Jason Hunter 和 Brett McLaughlin公開發(fā)布了它的1.0版本。在直覺、簡單和高效的前提下,這些API函數(shù)被最大限度的優(yōu)化。在接下來的篇幅里將介紹怎么用Jdom去讀寫一個已經(jīng)存在的XML文檔。
關(guān)鍵詞:Java、JDOM、XML
java+xml=Jdom!
這就是Jdom設(shè)計者的目標(biāo)。如果你曾經(jīng)是用過煩人的SAX或Dom來處理xml,你就會知道為什么要有JDOM.在2002的javaOne會議上JDOM的主要創(chuàng)始人jason Hunter有一篇精彩的演講介紹了JDom技術(shù),土模就是jdom makes xml easy.
我們知道dom是用于與平臺和語言無關(guān)的方式表示xml文檔的官方W3C標(biāo)準(zhǔn),利用dom和sax api可以解析和處理 xml文檔。這里我們介紹的jdom是基于樹操作的純java api,應(yīng)該說他提供的是一套用于解析、創(chuàng)建、出來和實現(xiàn)xml的解決方案。
二、環(huán)境配置
在我的WINDOWS xp系統(tǒng)平臺上采用jdk-1_5_0_06作為開發(fā)和測試平臺。?
三、獲得與安裝JDOM
由于目前JDOM并沒有包含在SUN的JDK中(我想不久的將來JDOM必然會成為SUN JDK的一部分),我們必須手工下載與設(shè)置JDOM的環(huán)境。
在
http://www.jdom.org可以下載JDOM的最新版本。這里下載的是jdom-1.0。JDOM的jar文件就是build目錄下的文件jdom.jar,將上述文件拷貝到j(luò)dk-1_5_0_06目錄下的jre/lib/ext目錄下,而用eclipse的用戶可以手動添加到user liberary
Jdom模型:
每個元素都有四個關(guān)鍵段:
?? 1、名稱
???2、元素屬性
???3、元素范圍名字空間
???4、元素內(nèi)容
用JDOM處理現(xiàn)有XML文檔的大致過程如下:
1、用簡單無變元構(gòu)造函數(shù)構(gòu)造一個org.jdom.input.SAXBuilder對象。SAXBuilder用sax解析器從文件中構(gòu)造文檔。SAXBuilder偵聽sax事件并從內(nèi)存中建立一個相應(yīng)的文檔。這種方式非常快(基本上和sax一樣快),Jdom的速度有值得期待的提高的潛力通過一個延期的構(gòu)造器的完成。這個構(gòu)造器檢查XML數(shù)據(jù)源,但當(dāng)請求的時候才對它解析。例如:文檔的屬性當(dāng)不訪問時是不需要解析的.構(gòu)造器仍在發(fā)展,可以通sql查詢、ldap查詢和其他的數(shù)據(jù)格式來夠造Jdom文檔。所以,一旦進到內(nèi)存中,文檔就和建造它的工具沒有關(guān)系了。
2、用建立器的build()方法從Reader,InputStream,URL,File或包含系統(tǒng)ID的字符串建立Document對象。
3、如果讀取文檔遇到問題,則拋出IOException,如果建立文檔遇到問題,則拋出JDOMException。
4、否則用Document類,Element類和其他JDOM類的方法在文檔中建立導(dǎo)航。
導(dǎo)航JDOM樹
每個Element對象包含一列子元素:Comment,ProcessingInstruction,Text和其他Element對象。此外,屬性和其他名字空間還有單獨的列表。
分析文檔和建立Document對象之后,可能要通過搜索來選擇其中程序感興趣的部分。在JDOM中,大多數(shù)導(dǎo)航通過Element類的方法進行。每個Element的完整子元素(包括了子元素的所有內(nèi)容,包括說明、處理指令、文本節(jié)點和元素,要進行深度搜索,就要對當(dāng)前元素的子元素應(yīng)用getContent()方法,通常要采用遞歸)在getContent()方法返回java.util.List中提供。getChildren()方法返回的java.util.List中只有每個Element的子元素。
JDOM的處理方式有些類似于DOM,但它主要是用SAX實現(xiàn)的,你不必擔(dān)心處理速度和內(nèi)存的問題。另外,JDOM中幾乎沒有接口,的類全部是實實在在的類,沒有類工廠類的。其最重要的一個包org.jdom中主要有以下類:
Document(文檔節(jié)點)
每個Document對象包括下列三個屬性:
1、根Element
2、表示文檔類型聲明的DocType對象
3、包含根元素和任何處理指令與說明的List,按文檔順序出現(xiàn)
Attribute(屬性節(jié)點)
Public Element setAttributes (List attributes)Throws IllegalAddException
Public List getAttributes()
setAttribute()
getAttribute()
getAttributeValue()
attribute.getName()
attribute.getValue()
CDATA (CDATA段節(jié)點)
Comment(說明節(jié)點)
XML文件的說明:<!-- wire configuration -->
DocType (文檔類型節(jié)點)
Element(元素節(jié)點)
元素名設(shè)置和獲取
Public Element setName(String name) throws IllegalNameException
Public String getName()
Public String? get(int i)? //i>=0
Content(內(nèi)容節(jié)點)
Public Element setContent(List list) throws IllegalAddException;
public List getContent();
addContent();
removeContent();
EntityRef(實例節(jié)點)
Namespace(名字空間節(jié)點)
ProcessingInstruction(處理指令節(jié)點)
Text(文本節(jié)點)
getText();
setText(String s);
?
example.xml文件
<?xml version="1.0" encoding="GBK"?>
<bookList>
? <book>
<name>Java編程入門</name>
????? <author>張三</author>
????? <publishDate>2002-6-6</publishDate>
????? <price>35.0</price>
? </book>
? <book>
????? <name>XML在Java中的應(yīng)用</name>
????? <author>李四</author>
????? <publishDate>2002-9-16</publishDate>
????? <price>92.0</price>
? </book>
</bookList>
cute.xml文件
<?xml version="1.0" encoding="gb2312"?>???
<bookList> ????//RootElement
? <book hot="true"> ???//<childelement name="value">---->Attribute
????? <name>Java編程入門</name> ?//<element>This is my text content</element>
????? <author>cute</author>
????? <publishDate>2002-6-6</publishDate>
????? <price>50.0</price>
? </book>
? <book>
????? <name>XML在Java中的應(yīng)用</name>
????? <author>李四</author>
????? <publishDate>2002-9-16</publishDate>
????? <price>92.0</price>
? </book>
</bookList>
數(shù)據(jù)輸入要用到XML文檔要通過org.jdom.input包,反過來需要org.jdom.output。如前面所說,關(guān)是看API文檔就能夠使用。
我們的例子讀入XML文件example.xml,加入一條處理指令,修改第一本書的價格和作者,并添加一條屬性,然后寫入文件cute.xml
cute.java:
package jdom;
import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;
import java.io.*;
import java.util.*;
public class Cute {
?public static void main(String args[]) {
??try {
???/*
??? * 用無變元構(gòu)造函數(shù)構(gòu)造一個SAXBuilder對象, 用sax解析器從文件中構(gòu)造文檔,
??? * SAXBuilder偵聽sax事件并從內(nèi)存中建立一個相應(yīng)的文檔
??? */
???SAXBuilder sb = new SAXBuilder();
???// 創(chuàng)建文檔
???Document doc = sb.build(new FileInputStream("example.xml"));
???// 加入一條處理指令
???ProcessingInstruction pi = new ProcessingInstruction(
?????"xml-stylesheet",
?????"href=\"bookList.html.xsl\" type=\"text/xsl\"");
???// 把這條處理指令,加入文檔中
???doc.addContent(pi);
???// 獲得這個文檔的根元素
???Element root = doc.getRootElement();
?? java.util.List ls = root.getChildren();
?? // 獲得這個根元素的所有子元素(不包含子元素的子元素),卻完全忽略其內(nèi)容? Iterator i = ls.iterator();
??? while (i.hasNext()) {
????Object o = i.next();
????if (o instanceof Text)/*使用instanceof 來獲得所需要的內(nèi)容*/
????{Text t=(Text)o;
?????System.out.println("Text: " + t.getText());}
????else if(o instanceof Attribute)
?????System.out.println("Attribute: " + o);
????else if (o instanceof Element)
?????System.out.println("Element: " + ((Element) o).getName());
???}
???
???// 得到第一個子元素的子元素,卻完全忽略其內(nèi)容
???Element book = (Element) ls.get(0);
???// 給這個子元素添加一條屬性,
???Attribute attr = new Attribute("hot", "true");
???book.setAttribute(attr);
???// 獲得這個元素的子元素(指定)以及其值
???Element el2 = book.getChild("author");
???// 輸出這個元素的值
???System.out.println(el2.getName());
???// 給這個元素的值改個名字
???el2.setText("cute");
???// 再獲得這個元素的子元素(指定)
???Element el3 = book.getChild("price");
???// 給這個值換個值
???el3.setText(Float.toString(50.0f));
???String indent = " ";
?? boolean newLines = true;
?? XMLOutputter xml = new XMLOutputter(indent, newLines, "gb2312");
?? xml.output(doc, new FileOutputStream("e:\\cute.xml"));???
??} catch (Exception e) {
???System.out.println(e.getMessage());
??}
?}
}