一、JDOM 簡(jiǎn)介
JDOM是一個(gè)開源項(xiàng)目,它基于樹型結(jié)構(gòu),利用純JAVA的技術(shù)對(duì)XML文檔實(shí)現(xiàn)解析、生成、序列化以及多種操作。
JDOM 直接為JAVA編程服務(wù)。它利用更為強(qiáng)有力的JAVA語言的諸多特性(方法重載、集合概念以及映射),把SAX和DOM的功能有效地結(jié)合起來。
在使用設(shè)計(jì)上盡可能地隱藏原來使用XML過程中的復(fù)雜性。利用JDOM處理XML文檔將是一件輕松、簡(jiǎn)單的事。
JDOM 在2000年的春天被Brett McLaughlin和Jason Hunter開發(fā)出來,以彌補(bǔ)DOM及SAX在實(shí)際應(yīng)用當(dāng)中的不足之處。
這些不足之處主要在于SAX沒有文檔修改、隨機(jī)訪問以及輸出的功能,而對(duì)于DOM來說,JAVA程序員在使用時(shí)來用起來總覺得不太方便。
DOM的缺點(diǎn)主要是來自于由于Dom是一個(gè)接口定義語言(IDL),它的任務(wù)是在不同語言實(shí)現(xiàn)中的一個(gè)最低的通用標(biāo)準(zhǔn),并不是為JAVA特別設(shè)計(jì)的。JDOM的最新版本為JDOM Beta 9。最近JDOM被收錄到JSR-102內(nèi),這標(biāo)志著JDOM成為了JAVA平臺(tái)組成的一部分。


二、JDOM 包概覽
JDOM是由以下幾個(gè)包組成的
org.JDOM
org.JDOM.input
org.JDOM.output
org.JDOM.adapters
org.JDOM.transform

三、JDOM 類說明

org.JDOM
這個(gè)包里的類是你解析xml文件后所要用到的所有數(shù)據(jù)類型。
Attribute
CDATA
Coment
DocType
Document
Element
EntityRef
Namespace
ProscessingInstruction
Text

org.JDOM.transform
在涉及xslt格式轉(zhuǎn)換時(shí)應(yīng)使用下面的2個(gè)類
JDOMSource
JDOMResult

org.JDOM.input
輸入類,一般用于文檔的創(chuàng)建工作
SAXBuilder
DOMBuilder
ResultSetBuilder

org.JDOM.output
輸出類,用于文檔轉(zhuǎn)換輸出
XMLOutputter
SAXOutputter
DomOutputter
JTreeOutputter

使用前注意事項(xiàng):
1.JDOM對(duì)于JAXP 以及 TRax 的支持
JDOM 支持JAXP1.1:你可以在程序中使用任何的parser工具類,默認(rèn)情況下是JAXP的parser。
制定特別的parser可用如下形式
SAXBuilder parser
= new SAXBuilder("org.apache.crimson.parser.XMLReaderImpl");
Document doc = parser.build("http://www.cafeconleche.org/");
// work with the document
JDOM也支持TRaX:XSLT可通過JDOMSource以及JDOMResult類來轉(zhuǎn)換(參見以后章節(jié))
2.注意在JDOM里文檔(Document)類由org.JDOM.Document 來表示。這要與org.w3c.dom中的Document區(qū)別開,這2種格式如何轉(zhuǎn)換在后面會(huì)說明。
以下如無特指均指JDOM里的Document。


四、JDOM主要使用方法
1.Ducument類
(1)Document的操作方法:
Element root = new Element("GREETING");
Document doc = new Document(root);
root.setText("Hello JDOM!");
或者簡(jiǎn)單的使用Document doc = new Document(new Element("GREETING").setText("Hello JDOM!t"));

這點(diǎn)和DOM不同。Dom則需要更為復(fù)雜的代碼,如下:
DocumentBuilde***ctory factory =DocumentBuilde***ctory.newInstance();
DocumentBuilder builde* =**ctory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root =doc.createElement("root");
Text text = doc.createText("This is the root");
root.appendChild(text);
doc.appendChild(root);


注意事項(xiàng):JDOM不允許同一個(gè)節(jié)點(diǎn)同時(shí)被2個(gè)或多個(gè)文檔相關(guān)聯(lián),要在第2個(gè)文檔中使用原來老文檔中的節(jié)點(diǎn)的話。首先需要使用detach()把這個(gè)節(jié)點(diǎn)分開來。

(2)從文件、流、系統(tǒng)ID、URL得到Document對(duì)象:
DOMBuilder builder = new DOMBuilder();
Document doc = builder.build(new File("jdom_test.xml"));

SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(url);
在新版本中DOMBuilder 已經(jīng)Deprecated掉 DOMBuilder.builder(url),用SAX效率會(huì)比較快。

這里舉一個(gè)小例子,為了簡(jiǎn)單起見,使用String對(duì)象直接作為xml數(shù)據(jù)源:


public jdomTest()
{
String textXml = null;
textXml = "<note>";
textXml = textXml +
"<to>aaa</to><from>bbb</from><heading>ccc</heading><body>ddd</body>";
textXml = textXml + "</note>";
SAXBuilder builder = new SAXBuilder();
Document doc = null;
Reader in= new StringReader(textXml);

try
{
doc = builder.build(in);
Element root = doc.getRootElement();
List ls = root.getChildren();//注意此處取出的是root節(jié)點(diǎn)下面的一層的Element集合

for (Iterator iter = ls.iterator(); iter.hasNext(); )
{
Element el = (Element) iter.next();

if(el.getName().equals("to"))
{
System.out.println(el.getText());
}
}
}

catch (IOException ex)
{
ex.printStackTrace();
}

catch (JDOMException ex)
{
ex.printStackTrace();
}
}

很簡(jiǎn)單把。


(3)DOM的document和JDOM的Document之間的相互轉(zhuǎn)換使用方法,簡(jiǎn)單!
DOMBuilder builder = new DOMBuilder();
org.jdom.Document jdomDocument = builder.build(domDocument);
// work with the JDOM document…

DOMOutputter converter = new DOMOutputter();
org.w3c.dom.Document domDocument = converter.output(jdomDocument);
// work with the DOM document…

2.XML文檔輸出
XMLOutPutter類:
JDOM的輸出非常靈活,支持很多種io格式以及風(fēng)格的輸出
Document doc = new Document(
);
XMLOutputter outp = new XMLOutputter();
// Raw output
outp.output(doc, fileOutputStream);
// Compressed output
outp.setTextTrim(true);
outp.output(doc, socket.getOutputStream());
// Pretty output
outp.setIndent(" ");
outp.setNewlines(true);
outp.output(doc, System.out);


詳細(xì)請(qǐng)參閱最新的JDOM API手冊(cè)


3.Element 類:
(1)瀏覽Element樹
//獲得根元素element
Element root = doc.getRootElement();
// 獲得所有子元素的一個(gè)list
List allChildren = root.getChildren();
// 獲得指定名稱子元素的list
List namedChildren = root.getChildren("name");
//獲得指定名稱的第一個(gè)子元素
Element child = root.getChild("name");
(這里的List是java.util.List)

JDOM給了我們很多很靈活的使用方法來管理子元素
List allChildren = root.getChildren();
// 刪除第四個(gè)子元素
allChildren.remove(3);
// 刪除叫“jack”的子元素
allChildren.removeAll(root.getChildren("jack"));

root.removeChildren("jack"); // 便捷寫法
// 加入
allChildren.add(new Element("jane"));

root.addContent(new Element("jane")); // 便捷寫法
allChildren.add(0, new Element("first"));


(2)移動(dòng)Elements:
在JDOM里很簡(jiǎn)單
Element movable = new Element("movable");
parent1.addContent(movable); // place
parent1.removeContent(movable); // remove
parent2.addContent(movable); // add

在Dom里
Element movable = doc1.createElement("movable");
parent1.appendChild(movable); // place
parent1.removeChild(movable); // remove
parent2.appendChild(movable); // 出錯(cuò)!

補(bǔ)充:
糾錯(cuò)性
JDOM的Element構(gòu)造函數(shù)(以及它的其他函數(shù))會(huì)檢查element是否合法。
而它的add/remove方法會(huì)檢查樹結(jié)構(gòu),檢查內(nèi)容如下:
1.在任何樹中是否有回環(huán)節(jié)點(diǎn)
2.是否只有一個(gè)根節(jié)點(diǎn)
3.是否有一致的命名空間(Namespaces)



(3)Element的text內(nèi)容讀取
<description>
A cool demo
</description>

// The text is directly available
// Returns "\n A cool demo\n"
String desc = element.getText();

// There's a convenient shortcut
// Returns "A cool demo"
String desc = element.getTextTrim();

(4)Elment內(nèi)容修改
element.setText("A new description");
3.可正確解釋特殊字符
element.setText("<xml> content");
4.CDATA的數(shù)據(jù)寫入、讀出
element.addContent(new CDATA("<xml> content"));
String noDifference = element.getText();

混合內(nèi)容
element可能包含很多種內(nèi)容,比如說


<!-- Some comment -->
Some text
Some child element


取table的子元素tr
String text = table.getTextTrim();
Element tr = table.getChild("tr");

也可使用另外一個(gè)比較簡(jiǎn)單的方法
List mixedCo = table.getContent();
Iterator itr = mixedCo.iterator();

while (itr.hasNext())
{
Object o = i.next();

if (o instanceof Comment)
{

}
// 這里可以寫成Comment, Element, Text, CDATA,ProcessingInstruction, 或者是EntityRef的類型
}
// 現(xiàn)在移除Comment,注意這里游標(biāo)應(yīng)為1。這是由于回車鍵也被解析成Text類的緣故,所以Comment項(xiàng)應(yīng)為1。
mixedCo.remove(1);



4.Attribute類

//獲得attribute
String width = table.getAttributeValue("width");
int border = table.getAttribute("width").getIntValue();
//設(shè)置attribute
table.setAttribute("vspace", "0");
// 刪除一個(gè)或全部attribute
table.removeAttribute("vspace");
table.getAttributes().clear();



5.處理指令(Processing Instructions)操作
一個(gè)Pls的例子
<?br?>
<?cocoon-process type="xslt"?>
| |
| |
目標(biāo) 數(shù)據(jù)

處理目標(biāo)名稱(Target)
String target = pi.getTarget();
獲得所有數(shù)據(jù)(data),在目標(biāo)(target)以后的所有數(shù)據(jù)都會(huì)被返回。
String data = pi.getData();
獲得指定屬性的數(shù)據(jù)
String type = pi.getValue("type");
獲得所有屬性的名稱
List ls = pi.getNames();

6.命名空間操作
<xhtml:html
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:title>Home Page</xhtml:title>
</xhtml:html>

Namespace xhtml = Namespace.getNamespace("xhtml", "http://www.w3.org/1999/xhtml");
List kids = html.getChildren("title", xhtml);
Element kid = html.getChild("title", xhtml);
kid.addContent(new Element("table", xhtml));

7.XSLT格式轉(zhuǎn)換
使用以下函數(shù)可對(duì)XSLT轉(zhuǎn)換
最后如果你需要使用w3c的Document則需要轉(zhuǎn)換一下。
public static Document transform(String stylesheet,Document in)

throws JDOMException
{

try
{
Transformer transformer = Transforme***ctory.newInstance()
.newTransformer(new StreamSource(stylesheet));
JDOMResult out = new JDOMResult();
transformer.transform(new JDOMSource(in), out);
return out.getDeocument();
}

catch (TransformerException e)
{
throw new JDOMException("XSLT Trandformation failed", e);
}
}

















對(duì)xml文檔的解析java中有很多種方法,例如使用dom、sax、jdom等等,相比之下,我覺得還是jdom比較方便。下面介紹一下jdom的基本使用方法,不對(duì)之處還請(qǐng)各位網(wǎng)友之交。謝謝!

最新的jdom可以到他的網(wǎng)站:http://www.jdom.org/去下載,現(xiàn)在的版本是1.0版,下載之后將得到j(luò)dom-1.0.zip文件,解壓后進(jìn)入build文件夾將看到一個(gè)名為jdom.jar的包,這個(gè)就是jdom的類包了,將它加到你的classpath里就可以使用jdom提供的各種處理xml的類和他們的方法了。應(yīng)該注意的是在解壓后的文件夾里還有一個(gè)lib文件夾,里面保存的是使用jdom的環(huán)境包,不過我在我的jdk1.4下使用沒引用這些包一樣好用,不知道是jdk1.4中已經(jīng)包含了這些東西還是原來我的eclipse已經(jīng)引用了這些包,呵呵。好了,書歸正傳,現(xiàn)在開始介紹jdom包的使用。jdom包的結(jié)構(gòu)包括:org.jdom 包含了所有的xml文檔要素的java類org.jdom.adapters 包含了與dom適配的java類org.jdom.filter 包含了xml文檔的過濾器類org.jdom.input 包含了讀取xml文檔的類org.jdom.output 包含了寫入xml文檔的雷o(hù)rg.jdom.transform 包含了將jdom xml文檔接口轉(zhuǎn)換為其他xml文檔接口org.jdom.xpath 包含了對(duì)xml文檔xpath操作的類下面將通過一個(gè)例子介紹jdom的常用操作

生成xml文檔:下面的類將生成一個(gè)xml文檔:

import java.io.*;import org.jdom.*;import org.jdom.output.*;public class WriteXML
{ public void BuildXML() throws Exception
{ Element root,student,number,name,age; root = new Element("student-info"); //生成根元素:student-info student = new Element("student"); //生成元素:student,該元素中將包含元素number,name,age number = new Element("number"); name = new Element("name"); age = new Element("age"); Document doc = new Document(root); //將根元素植入文檔doc中 number.setText("001"); name.setText("lnman"); age.setText("24"); student.addContent(number); student.addContent(name); student.addContent(age); root.addContent(student); Format format = Format.getCompactFormat(); format.setEncoding("gb2312"); //設(shè)置xml文件的字符為gb2312 format.setIndent(" "); //設(shè)置xml文件的縮進(jìn)為4個(gè)空格 XMLOutputter XMLOut = new XMLOutputter(format);//在元素后換行,每一層元素縮排四格 XMLOut.output(doc, new FileOutputStream("studentinfo.xml")); } public static void main(String[] args) throws Exception { WriteXML w = new WriteXML(); System.out.println("Now we build an XML document
.."); w.BuildXML(); System.out.println("finished!"); }}生成的xml文檔為:
<?xml version="1.0" encoding="gb2312"?><student-info> <student> <number>001</number> <name>lnman</name> <age>24</age> </student></student-info>

讀取xml文檔的例子:/** *//** Created on 2004-10-9* *用jdom讀取xml文檔的例子**//** *//*** @author lnman** To change the template for this generated type comment go to* Window>Preferences>Java>Code Generation>Code and Comments*/import org.jdom.output.*;import org.jdom.input.*;import org.jdom.*;import java.io.*;import java.util.*;public class ReadXML
{ public static void main(String[] args) throws Exception
{

SAXBuilder builder = new SAXBuilder(); Document read_doc = builder.build("studentinfo.xml"); Element stu = read_doc.getRootElement(); List list = stu.getChildren("student"); for(int i = 0;i < list.size();i++)
{ Element e = (Element)list.get(i); String str_number = e.getChildText("number"); String str_name = e.getChildText("name"); String str_age = e.getChildText("age"); System.out.println("---------STUDENT--------------"); System.out.println("NUMBER:" + str_number); System.out.println("NAME:" + str_name); System.out.println("AGE:" + str_age); System.out.println("------------------------------"); System.out.println(); } }}
Xpath例子:
JDOM的關(guān)于XPATH的api在org.jdom.xpath這個(gè)包里。這個(gè)包下,有一個(gè)抽象類XPath.java和實(shí)現(xiàn)類JaxenXPath.java, 使用時(shí)先用XPath類的靜態(tài)方法newInstance(String xpath)得到XPath對(duì)象,然后調(diào)用它的selectNodes(Object context)方法或selectSingleNode(Object context)方法,前者根據(jù)xpath語句返回一組節(jié)點(diǎn)(List對(duì)象);后者根據(jù)一個(gè)xpath語句返回符合條件的第一個(gè)節(jié)點(diǎn)(Object類型)。請(qǐng)看jdom-1.0自帶的范例程序:
它分析在web.xml文件中的注冊(cè)的servlet的個(gè)數(shù)及參數(shù)個(gè)數(shù),并輸出角色名。
web.xml文件:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
--> <web-app>
<servlet>
<servlet-name>snoop</servlet-name>
<servlet-class>SnoopServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>file </servlet-name>
<servlet-class>ViewFile</servlet-class>
<init-param>
<param-name>initial</param-name>
<param-value>1000</param-value>
<description>The initial value for the counter <!-- optional --></description>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mv</servlet-name>
<url-pattern>*.wm</url-pattern>
</servlet-mapping>
<distributed/> <security-role>
<role-name>manager</role-name>
<role-name>director</role-name>
<role-name>president</role-name>
</security-role>
</web-app>
處理程序:
import java.io.*;
import java.util.*;
import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;

import org.jdom.xpath.*; public class XPathReader
{


public static void main(String[] args) throws IOException, JDOMException
{

if (args.length != 1)
{
System.err.println("Usage: java XPathReader web.xml");
return;
}
String filename = args[0];//從命令行輸入web.xml
PrintStream out = System.out; SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new File(filename));//得到Document對(duì)象 // Print servlet information
XPath servletPath = XPath.newInstance("//servlet");//,選擇任意路徑下servlet元素
List servlets = servletPath.selectNodes(doc);//返回所有的servlet元素。 out.println("This WAR has "+ servlets.size() +" registered servlets:");
Iterator i = servlets.iterator();

while (i.hasNext())
{//輸出servlet信息
Element servlet = (Element) i.next();
out.print("\t" + servlet.getChild("servlet-name")
.getTextTrim() +
" for " + servlet.getChild("servlet-class")
.getTextTrim());
List initParams = servlet.getChildren("init-param");
out.println(" (it has " + initParams.size() + " init params)");
}

// Print security role information
XPath rolePath = XPath.newInstance("//security-role/role-name/text()");
List roleNames = rolePath.selectNodes(doc);//得到所有的角色名 if (roleNames.size() == 0) {
out.println("This WAR contains no roles");

} else
{
out.println("This WAR contains " + roleNames.size() + " roles:");
i = roleNames.iterator();

while (i.hasNext())
{//輸出角色名
out.println("\t" + ((Text)i.next()).getTextTrim());
}
}
}
} 輸出結(jié)果:
C:\java>java XPathReader web.xml [color=LimeGreen][/color]
This WAR has 2 registered servlets:
snoop for SnoopServlet (it has 0 init params)
file for ViewFile (it has 1 init params)
This WAR contains 3 roles:
manager
director
president