JDom解析和產生XML文檔

來源:互聯網
上載者:User

原創作品,允許轉載,轉載時請務必以超連結形式標明文章 原始出處 、作者資訊和本人聲明。否則將追究法律責任。
作者:永恒の_☆ 地址:http://blog.csdn.net/chenghui0317/article/details/12137845一、前言

    JDom是一套非常優秀的java開源api,主要用於讀寫xml文檔,具有效能優異、功能強大、和非常方便使用的特點,並且把jdk內建的解析方式SAX和Dom的功能有效地結合起來。經過實踐操作發現dom4j和jdom解析xml的時候有一些相似的地方,故可以比對一下解析的效能和實現方式的效率。


二、準備條件

:http://download.csdn.net/detail/ch656409110/6334543


三、使用JDom實戰


1、解析xml文檔

實現思路:

   <1>建立SAX建立者對象的執行個體;

   <2>根據讀取的xml路徑,傳遞給SAXBuilder的執行個體之後 返回一個Document文檔對象;

   <3>然後操作這個Document對象,擷取下面的節點以及子節點的資訊。

具體代碼如下:

import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.List;import org.jdom.DocType;import org.jdom.Document;import org.jdom.Element;import org.jdom.JDOMException;import org.jdom.input.SAXBuilder;import org.jdom.output.XMLOutputter;import org.xml.sax.InputSource;/** * 使用JDom操作xml的簡單例子 * @author Administrator * */public class JDomOperateXmlDemo {public void parseXml01(){        String xmlPath = "D:\\project\\dynamicWeb\\src\\resource\\document01.xml";          String xmlName = xmlPath.substring(xmlPath.lastIndexOf("\\")); try {//建立SAX建造者對象,該類構造方法的重載boolean類型的方法中validate表示是否驗證xml文檔。SAXBuilder saxBuilder = new SAXBuilder(false);//1、直接指定絕對路徑擷取檔案輸入資料流對象//InputStream inputStream = new FileInputStream(xmlPath);//2、使用類的相對路徑尋找xml路徑//InputStream inputStream = this.getClass().getResourceAsStream(xmlName);//3、也可以指定路徑完成InputStream輸入資料流的執行個體化操作              InputStream inputStream = new FileInputStream(new File(xmlPath));              //4、使用InputSource輸入源作為參數也可以轉換xml              InputSource inputSource = new InputSource(inputStream);            //解析xml文檔,返回document文檔對象            Document document = saxBuilder.build(inputSource);Element rootElement = document.getRootElement();//根節點System.out.println("根節點名稱:" + rootElement.getName());//擷取節點的名稱              System.out.println("根節點有多少屬性:" + rootElement.getAttributes().size());//擷取節點屬性數目              System.out.println("根節點id屬性的值:" + rootElement.getAttributeValue("id"));//擷取節點的屬性id的值              System.out.println("根節點內文本:" + rootElement.getText());//如果元素有子節點則返回Null 字元串,否則返回節點內的文本              //rootElement.getText() 之所以會換行是因為 標籤與標籤之間使用了tab鍵和分行符號布局,這個也算是文本所以顯示出來換行的效果。              System.out.println("根節點內文本(1):" + rootElement.getTextTrim());//去掉的是標籤與標籤之間的tab鍵和分行符號等等,不是內容前後的空格            System.out.println("根節點內文本(2):" + rootElement.getTextNormalize()); //目前發現和getTextTrim()方法效果一樣               System.out.println("根節點內文本(3):" + rootElement.getValue());  //返回節點下所有內容              Element element = rootElement.getChild("Element"); //擷取子節點,如果有多個Element節點,那麼返回最先讀取到的element            if(element != null){                  System.out.println("子節點的文本:" + element.getText());//因為子節點和根節點都是Element對象所以它們的操作方式都是相同的              }             //但是有些情況xml比較複雜,規範不統一,某個節點不存在直接java.lang.NullPointerException,所以擷取到element對象之後要先判斷一下是否為空白              List<Element> list = rootElement.getChildren("Element");//返回的是List集合            for (Element ele : list) {}} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {JDomOperateXmlDemo demo = new JDomOperateXmlDemo();demo.parseXml01();}}
另外上面的xml在src下面,document01.xml具體如下:

<?xml version="1.0" encoding="UTF-8" ?><Document id="doc01">根節點的內容<Element>子節點的內容</Element> </Document>
接下來執行該類的main方法,console效果如下:


根據控制台顯示可知:

   <1>如果new SAXBuilder(false)指定為true,指定運行會報錯:  簡單的說就是沒有匯入文法檔案,比如dtd檔案等等,所以jdom在驗證xml規範的時候還是非常嚴格的;
   <2>這裡發現jdom解析xml區分大小寫,就是區分指定節點名稱,但是dom4j是不區分的;

   <3>有些情況xml比較複雜,規範不統一,某個節點不存在直接報錯:,所以擷取到element對象之後要先判斷一下是否為空白。


上面只是簡單的擷取了xml的根目錄的元素,接下來使用ArrayList集合迴圈document文檔對象。

具體代碼如下:

public void parseXml02(){String xmlPath = "D:\\project\\dynamicWeb\\src\\resource\\document02.xml";  try {//建立SAX建造者對象,該類構造方法的重載boolean類型的方法中validate表示是否驗證xml文檔。SAXBuilder saxBuilder = new SAXBuilder(false);InputStream inputStream = new FileInputStream(new File(xmlPath));  //解析xml文檔,返回document文檔對象Document document = saxBuilder.build(inputStream);Element rootElement = document.getRootElement();//根節點List<Element> elementList = rootElement.getChildren("Element");for (Element element : elementList) {System.out.println("【" + element.getName() + "】:" + element.getTextTrim());//如果有子節點就返回Null 字元串Element nameElement = element.getChild("name");if(nameElement != null){System.out.println("   " + nameElement.getName() + ":" + nameElement.getTextTrim());}Element valueElement = element.getChild("value");if(valueElement != null){System.out.println("   " + valueElement.getName() + ":" + valueElement.getTextTrim());}Element descriptElement = element.getChild("descript");if(descriptElement != null){System.out.println("   " + descriptElement.getName() + ":" + descriptElement.getTextTrim());}}} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
另外上面的xml在src下面,document02.xml具體如下:

<?xml version="1.0" encoding="UTF-8" ?><Document id="doc01">根節點的內容<Element>子節點的內容</Element><Element id="ele01"><name><![CDATA[節點的名稱]]></name><value><![CDATA[節點的值]]></value><descript><![CDATA[節點的描述]]></descript></Element><Element id="ele02"><name><![CDATA[節點的名稱<2>]]></name><value><![CDATA[節點的值<2>]]></value><descript><![CDATA[節點的描述<2>]]></descript></Element> </Document>
接下來執行該類的main方法,console效果如下:


根據控制台顯示可知:

   <1>直接解析就會報錯:  因為標籤的內容中包含標籤標記符號,使用<![CDATA[]]>標記會被當成文本資訊不被解析;
   <2>因為是getChildren("Element");有指定具體元素名稱,所以只會擷取Element節點,另外節點的子節點包含Element節點不會被擷取,所以getChildren("Element");沒有遞迴擷取子項目;


jdom不但能夠解析xml對象,並且在解析的時候還可以操作document對象,重新構造一個新的Document文檔對象。

具體代碼如下:

public void operateXml01(){        String xmlPath = "D:\\project\\dynamicWeb\\src\\resource\\document03.xml";  try {//建立SAX建造者對象,該類構造方法的重載boolean類型的方法中validate表示是否驗證xml文檔。SAXBuilder saxBuilder = new SAXBuilder(false);InputStream inputStream = new FileInputStream(new File(xmlPath));  //4、使用InputSource輸入源作為參數也可以轉換xml  InputSource inputSource = new InputSource(inputStream);//解析xml文檔,返回document文檔對象Document document = saxBuilder.build(inputSource);Element rootElement = document.getRootElement();//根節點/*        rootElement.setName("root");//支援修改節點名稱          System.out.println("根節點修改之後的名稱:" + rootElement.getName());          rootElement.setText("text"); //同樣修改標籤內的文本也一樣          System.out.println("根節點修改之後的文本:" + rootElement.getText());          */        //接下來根據id擷取元素 添加子項目或者刪除子節點        List<Element> elementList = rootElement.getChildren();        System.out.println("刪除節點前的集合個數:"+elementList.size());        for (Element element : elementList) {        if(element.getAttributeValue("id")!=null){if(element.getAttributeValue("id").equals("ele01")){Element element01 = new Element("new_name");element01.setText("新添加的名稱");Element element02 = new Element("new_value");element02.setText("新添加的名稱");Element element03 = new Element("new_descript");element03.setText("新添加的名稱");element.addContent(element01);element.addContent(element02);element.addContent(element03);}else if(element.getAttributeValue("id").equals("ele02")){/*rootElement.removeContent(element);break;*/element.removeContent();System.out.println("刪除節點後的集合個數:"+elementList.size());}        }}        elementList = rootElement.getChildren("Element");for (Element element : elementList) {System.out.println("【" + element.getName() + "】:" + element.getTextTrim());//如果有子節點就返回Null 字元串Element nameElement = element.getChild("new_name");if(nameElement != null){System.out.println("   " + nameElement.getName() + ":" + nameElement.getTextTrim());}Element valueElement = element.getChild("new_value");if(valueElement != null){System.out.println("   " + valueElement.getName() + ":" + valueElement.getTextTrim());}Element descriptElement = element.getChild("new_descript");if(descriptElement != null){System.out.println("   " + descriptElement.getName() + ":" + descriptElement.getTextTrim());}}} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
另外上面的xml在src下面,document03.xml具體如下:
<?xml version="1.0" encoding="UTF-8" ?><Document id="doc01">根節點的內容<Element>子節點的內容</Element><Element id="ele01"><Content>節點內容1</Content></Element><Element id="ele02"><Content>節點內容2</Content></Element> </Document>
接下來執行該類的main方法,console效果如下:

根據控制台顯示可知:

   <1>執行上面的修改根節點操作會影響下面,因為setText()會直接覆蓋掉根節點下的子節點;
   <2>開始刪除節點使用的是直接刪除節點的方法,直接報錯:  除非刪除之後立刻執行另外調用就不會出現這樣的問題;

   <3>根據輸出節點集合的個數可知,再迴圈的時候改變集合數量會直接影響迴圈,因為迴圈過程中並沒有隨著數量的修改而改變迴圈的次數。但element.removeContent(); 不一樣,迴圈至始至終集合數量都沒有發生改變,只是將這個節點的引用置為null了。


2、產生xml文檔

JDom能夠解析xml,同樣肯定能產生xml,而且使用起來更加簡單方便。

實現思路:

   <1>建立Document對象,添加節點以及節點下的文本、名稱和屬性值;

   <2>建立XMLOutputter的執行個體,調用output()方法把document寫入磁碟;

具體代碼如下:

public void buildXml01(){//自己封裝xml文檔對象Element rootElement = new Element("Document");Element element = new Element("Element");Element nameElement = new Element("name");nameElement.setText("<名稱>");Element valueElement = new Element("value");valueElement.setText("<值 >\"\\");Element descriptionElement = new Element("description");descriptionElement.setText("<描述><![CDATA[<查看是否轉義儲存>]]>");//添加子節點element.addContent(nameElement);element.addContent(valueElement);element.addContent(descriptionElement);rootElement.addContent(element);Document document = new Document(rootElement);DocType docType = new DocType("Doctype");document.setDocType(docType);XMLOutputter xmloutputter = new XMLOutputter();OutputStream outputStream;try {outputStream = new FileOutputStream("c:\\document.xml");xmloutputter.output(document, outputStream);System.out.println("xml文檔產生成功!");} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

接下來執行該類的main方法,console提示產生成功。

然後到c盤根目錄尋找document.xml,具體如下:

實踐發現:

   <1>如果不指定編碼,產生的xml預設是UTF-8編碼的;
   <2>節點內的常值內容包含標籤標記符都會被轉義成&lt; &gt; ,,但是其他特殊符號就不會,比如空格,雙引用,單引號,斜杠 等等。


三、幾種解析XML方式的比較

前面依次介紹了三種操作xml的方式,分別是:

   Dom4j解析和產生XML文檔,  地址:http://blog.csdn.net/chenghui0317/article/details/11486271

   Dom解析和產生XML文檔,  地址:http://blog.csdn.net/chenghui0317/article/details/11662667

   SAX解析和產生XML文檔,  地址:http://blog.csdn.net/chenghui0317/article/details/11990891 

   <1>Dom4j的xml解析效能最好,目前有許多開源項目都在使用Dom4j解析xml文檔,比如hibernate,另外Dom4j解析的時候採用物件導向,所有的節點都是用Element封裝之後返回,非常方便使用和調用;

   <2>SAX解析xml效能較好,因為它是採用DefaultHandler事件處理者來解析的,但是不好的地方在於每一個節點的名稱,屬性和內容都被分開了,也沒有使用對象封裝,所以在解析之後封裝對象上面比較麻煩,稍微不注意就會使空文本覆蓋掉應該存放的值;

   <3>JDom在解析xml效能上表現不是很好,雖然JDom 和 Dom4j在解析上有很多相似之後,大多差距都是方法名稱不同但是具體含義相同,所以使用起來還是蠻方便的;

   <4>Dom在解析xml效能上表現也不是很好,另外Dom在解析xml使用的時候感覺是最不方便的,Dom並沒有把解析的節點封裝成對象,並且很容易受到非空內容的節點影響,導致解析拋異常。



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.