JDOM是一個開源項目,它基于樹型結構,利用純JAVA的技術對XML文檔實現解析、生成、序列化以及多種操作。
一、JDOM 簡介
JDOM是一個開源項目,它基于樹型結構,利用純JAVA的技術對XML文檔實現解析、生成、序列化以及多種操作。
JDOM 直接為JAVA編程服務。它利用更為強有力的JAVA語言的諸多特性(方法重載、集合概念以及映射),把SAX和DOM的功能有效地結合起來。
在使用設計上盡可能地隱藏原來使用XML過程中的復雜性。利用JDOM處理XML文檔將是一件輕松、簡單的事。
JDOM 在2000年的春天被Brett McLaughlin和Jason Hunter開發出來,以彌補DOM及SAX在實際應用當中的不足之處。
這些不足之處主要在于SAX沒有文檔修改、隨機訪問以及輸出的功能,而對于DOM來說,JAVA程序員在使用時來用起來總覺得不太方便。
DOM的缺點主要是來自于由于Dom是一個接口定義語言(IDL),它的任務是在不同語言實現中的一個最低的通用標準,并不是為JAVA特別設計的。JDOM的最新版本為JDOM Beta
?9。最近JDOM被收錄到JSR-102內,這標志著JDOM成為了JAVA平臺組成的一部分。
二、JDOM 包概覽
JDOM是由以下幾個包組成的
org.jdom??????????????? 包含了所有的xml文檔要素的java類
?
org.jdom.adapters???????? 包含了與dom適配的java類
?
org.jdom.filter??????????? 包含了xml文檔的過濾器類
?
org.jdom.input??????????? 包含了讀取xml文檔的類
?
org.jdom.output?????????? 包含了寫入xml文檔的類
?
org.jdom.transform??????? 包含了將jdom xml文檔接口轉換為其他xml文檔接口
?
org.jdom.xpath??????????? 包含了對xml文檔xpath操作的類三、JDOM 類說明
1、org.JDOM這個包里的類是你J解析xml文件后所要用到的所有數據類型。
Attribute
CDATA
Coment
DocType
Document
Element
EntityRef
Namespace
ProscessingInstruction
Text
2、org.JDOM.transform在涉及xslt格式轉換時應使用下面的2個類
JDOMSource
JDOMResult
org.JDOM.input
3、輸入類,一般用于文檔的創建工作
SAXBuilder
DOMBuilder
ResultSetBuilder
org.JDOM.output
4、輸出類,用于文檔轉換輸出
XMLOutputter
SAXOutputter
DomOutputter
JTreeOutputter
使用前注意事項:
1.JDOM對于JAXP 以及 TRax 的支持
JDOM 支持JAXP1.1:你可以在程序中使用任何的parser工具類,默認情況下是JAXP的parser。
制定特別的parser可用如下形式
SAXBuilder parser
? = new SAXBuilder("org.apache.crimson.parser.XMLReaderImpl");
?Document doc = parser.build("
?// work with the document... JDOM也支持TRaX:XSLT可通過JDOMSource以及JDOMResult類來轉換(參見以后章節) 2.注意在JDOM里文檔(Document)類由org.JDOM.Document 來表示。這要與org.w3c.dom中的Document區別開,這2種格式如何轉換在后面會說明。 以下如無特指均指JDOM里的Document。 四、JDOM主要使用方法 1.Ducument類 (1)Document的操作方法: Element root = new Element("GREETING"); Document doc = new Document(root); root.setText("Hello JDOM!"); 或者簡單的使用Document doc = new Document(new Element("GREETING").setText("Hello JDOM!t")); 這點和DOM不同。Dom則需要更為復雜的代碼,如下: DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance(); DocumentBuilder builder =factory.newDocumentBuilder(); Document doc = builder.newDocument(); Element root =doc.createElement("root"); Text text = doc.createText("This is the root"); root.appendChild(text); doc.appendChild(root); 注意事項:JDOM不允許同一個節點同時被2個或多個文檔相關聯,要在第2個文檔中使用原來老文檔中的節點的話。首先需要使用detach()把這個節點分開來。 (2)從文件、流、系統ID、URL得到Document對象: DOMBuilder builder = new DOMBuilder(); Document doc = builder.build(new File("jdom_test.xml")); SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(url); 在新版本中DOMBuilder 已經Deprecated掉 DOMBuilder.builder(url),用SAX效率會比較快。 這里舉一個小例子,為了簡單起見,使用String對象直接作為xml數據源: ?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節點下面的一層的Element集合 ????? for (Iterator iter = ls.iterator(); iter.hasNext(); ) { ??????? if(el.getName().equals("to")){ ???????? System.out.println(el.getText()); ??????? } ????? } ??? } ??? catch (IOException ex) { ????? ex.printStackTrace(); ??? } ??? catch (JDOMException ex) { ????? ex.printStackTrace(); ??? } ? } (3)DOM的document和JDOM的Document之間的相互轉換使用方法,簡單! DOMBuilder builder = new DOMBuilder(); org.jdom.Document jdomDocument = builder.build(domDocument); DOMOutputter converter = new DOMOutputter();// work with the JDOM document… org.w3c.dom.Document domDocument = converter.output(jdomDocument); // work with the DOM document… 2.XML文檔輸出 XMLOutPutter類: JDOM的輸出非常靈活,支持很多種io格式以及風格的輸出 Document doc = new Document(...); XMLOutputter outp = new XMLOutputter(); outp.output(doc, fileOutputStream); // Raw output outp.setTextTrim(true); // Compressed output outp.output(doc, socket.getOutputStream()); outp.setIndent(" ");// Pretty output outp.setNewlines(true); outp.output(doc, System.out); 詳細請參閱最新的JDOM API手冊 3.Element 類: (1)瀏覽Element樹 Element root = doc.getRootElement();//獲得根元素element List allChildren = root.getChildren();// 獲得所有子元素的一個list List namedChildren = root.getChildren("name");// 獲得指定名稱子元素的list Element child = root.getChild("name");//獲得指定名稱的第一個子元素 JDOM給了我們很多很靈活的使用方法來管理子元素(這里的List是java.util.List) List allChildren = root.getChildren(); allChildren.remove(3); // 刪除第四個子元素 allChildren.removeAll(root.getChildren("jack"));// 刪除叫“jack”的子元素 root.removeChildren("jack"); // 便捷寫法 allChildren.add(new Element("jane"));// 加入 root.addContent(new Element("jane")); // 便捷寫法 allChildren.add(0, new Element("first")); (2)移動Elements: 在JDOM里很簡單 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); // 出錯! 補充:糾錯性 JDOM的Element構造函數(以及它的其他函數)會檢查element是否合法。 而它的add/remove方法會檢查樹結構,檢查內容如下: 1.在任何樹中是否有回環節點 2.是否只有一個根節點 3.是否有一致的命名空間(Namespaces) (3)Element的text內容讀取 <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內容修改 element.setText("A new description"); 3.可正確解釋特殊字符 element.setText("<xml> content"); 4.CDATA的數據寫入、讀出 element.addContent(new CDATA("<xml> content")); String noDifference = element.getText(); 混合內容 element可能包含很多種內容,比如說 <table> <!-- Some comment --> Some text <tr>Some child element</tr> </table> 取table的子元素tr String text = table.getTextTrim(); Element tr = table.getChild("tr"); 也可使用另外一個比較簡單的方法 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的類型 } // 現在移除Comment,注意這里游標應為1。這是由于回車鍵也被解析成Text類的緣故,所以Comment項應為1。 mixedCo.remove(1); 4.Attribute類 <table width="100%" border="0"> </table> String width = table.getAttributeValue("width");//獲得attribute int border = table.getAttribute("width").getIntValue(); table.setAttribute("vspace", "0");//設置attribute table.removeAttribute("vspace");// 刪除一個或全部attribute table.getAttributes().clear(); 5.處理指令(Processing Instructions)操作 一個Pls的例子 <?br?> <?cocoon-process type="xslt"?> ????????? |??????? | ????????? |??????? | ??????? 目標???? 數據 處理目標名稱(Target) String target = pi.getTarget(); 獲得所有數據(data),在目標(target)以后的所有數據都會被返回。 String data = pi.getData(); String type = pi.getValue("type");獲得指定屬性的數據 List ls = pi.getNames();獲得所有屬性的名稱 6.命名空間操作 <xhtml:html ?xmlns:xhtml="
<xhtml:title>Home Page</xhtml:title> </xhtml:html> Namespace xhtml = Namespace.getNamespace("xhtml", "
List kids = html.getChildren("title", xhtml); Element kid = html.getChild("title", xhtml); kid.addContent(new Element("table", xhtml)); 7.XSLT格式轉換 使用以下函數可對XSLT轉換 最后如果你需要使用w3c的Document則需要轉換一下。 public static Document transform(String stylesheet,Document in) ??????????????????????????????????????? throws JDOMException { ???? try { ?????? Transformer transformer = TransformerFactory.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); ???? } ?? } 五、用例: 1、生成xml文檔: ? ? 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"); //設置xml文件的字符為gb2312 ??????? format.setIndent("??? "); //設置xml文件的縮進為4個空格 ??????? 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文檔2: ?public class CreateXML { ? public void Create() { ?? try { ??? Document doc = new Document();?? ??? ProcessingInstruction pi=new ProcessingInstruction("xml-stylesheet","type="text/xsl" href="test.xsl""); ??? doc.addContent(pi);??? ??? Namespace ns = Namespace.getNamespace("
??? Namespace ns2 = Namespace.getNamespace("other", "
??? Element root = new Element("根元素", ns); ??? root.addNamespaceDeclaration(ns2); ??? doc.setRootElement(root); ??? Element el1 = new Element("元素一"); ??? el1.setAttribute("屬性", "屬性一");??? ??? Text text1=new Text("元素值"); ???????????? Element em = new Element("元素二").addContent("第二個元素"); ??? el1.addContent(text1); ???????????? el1.addContent(em);???????????? ???????????? Element el2 = new Element("元素三").addContent("第三個元素"); ???????????? root.addContent(el1); ???????????? root.addContent(el2);???????????? ???????????? //縮進四個空格,自動換行,gb2312編碼 ???????????? XMLOutputter outputter = new XMLOutputter("? ", true,"GB2312"); ???????????? outputter.output(doc, new FileWriter("test.xml")); ???????? }catch(Exception e)? { ????????? System.out.println(e); ???????? } ???? }???? ???? public static void main(String args[]) { ????? new CreateXML().Create(); ???? }???? ?} 2、讀取xml文檔的例子: 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(); ??????? }? ?????? } } 3、DTD驗證的: ?public class XMLWithDTD { ? public void validate()? { ?? try { ??? SAXBuilder builder = new SAXBuilder(true); ??? builder.setFeature("); ??? Document doc = builder.build(new FileReader("author.xml"));??? ??? System.out.println("搞掂"); ??? XMLOutputter outputter = new XMLOutputter(); ??? outputter.output(doc, System.out); ?? }catch(Exception e) { ??? System.out.println(e); ?? }?? ? } ? public static void main(String args[]) { ?? new XMLWithDTD().validate(); ? }? ?} ? 需要說明的是,這個程序沒有指明使用哪個DTD文件。DTD文件的位置是在XML中指定的,而且DTD不支持命名空間,一個XML只能引用一個DTD,所以程序直接讀取XML中指定的DTD,程序本身不用指定。不過這樣一來,好象就只能使用外部式的DTD引用方式了?高人指點。 ? ? 4、XML Schema驗證的: ?public class XMLWithSchema { ? String xml="test.xml"; ? String schema="test-schema.xml"; ? public void validate() { ?? try { ??? SAXBuilder builder = new SAXBuilder(true); ??? //指定約束方式為XML schema ??? builder.setFeature("
??? //導入schema文件 builder.setProperty("); ??? Document doc = builder.build(new FileReader(xml));??? ??? System.out.println("搞掂"); ??? XMLOutputter outputter = new XMLOutputter(); ??? outputter.output(doc, System.out); ?? }catch(Exception e) { ??? System.out.println("驗證失敗:"+e); ?? }? ? } ?} ?上面的程序就指出了要引入的XML Schema文件的位置。 ? ? ?系統默認輸出是UTF-8,這有可能導致出現亂碼。 5、Xpath例子: JDOM的關于XPATH的api在org.jdom.xpath這個包里。這個包下,有一個抽象類XPath.java和實現類JaxenXPath.java, ???? 它分析在web.xml文件中的注冊的servlet的個數及參數個數,并輸出角色名。 web.xml文件: <?xml version="1.0" encoding="ISO-8859-1"?> <!-- <!DOCTYPE web-app ??? PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
?/*for(int i=0;i<ls.size; i++)
?Element el = (Element) list.get(i);
?*/
??????? Element el = (Element) iter.next();
使用時先用XPath類的靜態方法newInstance(String xpath)得到XPath對象,
然后調用它的selectNodes(Object context)方法或selectSingleNode(Object context)方法,
前者根據xpath語句返回一組節點(List對象);后者根據一個xpath語句返回符合條件的第一個節點(Object類型)。
請看jdom-1.0自帶的范例程序: