日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

常用 XML 解析技术

發(fā)布時(shí)間:2024/3/13 asp.net 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 常用 XML 解析技术 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

現(xiàn)在的軟件項(xiàng)目都不是獨(dú)立的一個(gè)項(xiàng)目,都是多系統(tǒng)協(xié)調(diào)工作。這樣的話就涉及到系統(tǒng)間的通訊,通訊就會(huì)跟報(bào)文傳輸掛上關(guān)系。系統(tǒng)間使用怎樣的報(bào)文格式進(jìn)行通訊呢?有的使用固定長(zhǎng)度格式報(bào)文;有的使用變長(zhǎng)格式報(bào)文;有的使用 XML格式報(bào)告。本場(chǎng) Chat 主要和大家分享一下 XML 格式報(bào)文的解析。Java 是一個(gè)開源的語(yǔ)言,本場(chǎng) Chat 將給大家介紹一下常用的 XML 解析框架及特點(diǎn)。

主要內(nèi)容:

  • XML 的簡(jiǎn)介及一些常見概念 ;
  • Java 內(nèi)置解析 XML API: DOM、SAX;
  • XML 解析框架 JDOM;
  • XML 解析框架 DOM4J;
  • XML 解析框架 XStream ;
  • 總結(jié) 。

現(xiàn)在的軟件項(xiàng)目都不是獨(dú)立的一個(gè)項(xiàng)目,都是多系統(tǒng)協(xié)調(diào)工作。這樣的話就涉及到系統(tǒng)間的通訊,通訊就會(huì)跟報(bào)文傳輸掛上關(guān)系。系統(tǒng)間使用怎樣的報(bào)文格式進(jìn)行通訊呢?有的使用固定長(zhǎng)度格式報(bào)文;有的使用變長(zhǎng)格式報(bào)文;有的使用 XML 格式報(bào)告。本分享主要和大家分享一下 XML 格式報(bào)文的解析。Java 是一個(gè)開源的語(yǔ)言,本分享將給大家介紹一下常用的 XML 解析框架及特點(diǎn)。

  • XML 的簡(jiǎn)介及一些常見概念
  • Java 內(nèi)置解析 XML API: DOM、SAX
  • XML 解析框架 JDOM
  • XML 解析框架 DOM4J
  • XML 解析框架 XStream
  • 總結(jié)

XML 的簡(jiǎn)介及一些常見概念

XML 的概念

XML 是 Extensible Markup Language 簡(jiǎn)稱,中文翻譯為可擴(kuò)展標(biāo)記語(yǔ)言。XML 是一種通用的數(shù)據(jù)交換格式,它的平臺(tái)無(wú)關(guān)性、語(yǔ)言無(wú)關(guān)性、系統(tǒng)無(wú)關(guān)性,給數(shù)據(jù)集成與交互帶來(lái)了極大的方便。XML 在不同的語(yǔ)言環(huán)境中解析方式都是一樣的,只不過(guò)實(shí)現(xiàn)的語(yǔ)法不同而已。

XML 可用來(lái)描述數(shù)據(jù)、存儲(chǔ)數(shù)據(jù)、傳輸數(shù)據(jù)/交換數(shù)據(jù)。

XML 文檔節(jié)點(diǎn)的類型主要有:

  • document:文檔,代表整個(gè)文檔(DOM 樹的根節(jié)點(diǎn));
  • element:元素,表示一個(gè)元素;
  • attribute:屬性,代表一個(gè)屬性;
  • PCDATA(Parsed Character Data):文本;
  • comment:注釋,代表一個(gè)注釋;
  • DOCTYPE:主要驗(yàn)證文檔內(nèi)容的正確性;
  • ENTITIES:實(shí)體;
  • CDATA(Character Data):代表文檔中的 CDATA 區(qū)段,文本不會(huì)被解析器解析。
  • XML 的基本語(yǔ)法

    在使用過(guò)程中,請(qǐng)記住以下幾個(gè)基本語(yǔ)法。

    • 聲明格式,如下:
    <?xml version="1.0" encoding="UTF-8"?>
    • 根節(jié)點(diǎn):必須有一個(gè)根節(jié)點(diǎn)。
    • 標(biāo)簽:標(biāo)簽必須有結(jié)束且區(qū)分大小寫,標(biāo)簽必須順序嵌套。
    • 屬性:必須使用引號(hào)引起值。
    • 空格會(huì)被保留。
    • 命名規(guī)則:命名必須見名知意。
      • 名字可包含字母、數(shù)字以及其他的字符。
      • 名字不能以數(shù)字或者標(biāo)點(diǎn)符號(hào)開始。
      • 名字不能以字符“xml”(或者 XML、Xml)開始。
    • 名字不能包含空格。
    • 不應(yīng)在 XML 元素名稱中使用“:” ,這是由于它用于命名空間(NameSpaces)的保留字。
    • 標(biāo)簽優(yōu)先于屬性。
    • XML 命名空間可提供避免元素命名沖突的方法。
    • CDATA:字符數(shù)據(jù),<![CDATA[字符數(shù)據(jù)]]> ,字符數(shù)據(jù)不進(jìn)行轉(zhuǎn)義。
    • 實(shí)體:使用方式為“&實(shí)體;”,XML 中有5個(gè)預(yù)定義的實(shí)體,如下表所示。
    實(shí)體名稱含義備注
    <<小于
    >>大于
    &&和號(hào)
    ''單引號(hào)
    ""引號(hào)

    注釋:在 XML 中,只有字符 "<" 和 "&" 確實(shí)是非法的。大于號(hào)是合法的,但是用實(shí)體引用來(lái)代替它是一個(gè)好習(xí)慣。

    XML 約束

    1.XML DTD 約束

    DTD 是 DocType Definition 的簡(jiǎn)稱,中文翻譯為文檔類型定義,DTD 的作用是定義 XML 文檔的合法構(gòu)建模塊。它使用一系列的合法元素來(lái)定義文檔結(jié)構(gòu),用于約定 XML 的格式。規(guī)定了文檔中所使用的元素、實(shí)體、元素的屬性、元素與實(shí)體之間的關(guān)系。

    DTD主要作用有:

    • 使用 DTD 可以提供一種統(tǒng)一的格式。

    XML 的可擴(kuò)展性為文檔的作者提供了很高的靈活性,可有時(shí)候需要的是統(tǒng)一,要求某一類文檔具有相同的結(jié)構(gòu)。

    • 使用 DTD 可以保證數(shù)據(jù)交流和共享的順利進(jìn)行。
    • DTD 使用戶能夠不依賴具體的數(shù)據(jù)就知道文檔的邏輯結(jié)構(gòu)。

    在沒(méi)有 XML 文檔的時(shí)候,也可以根據(jù) DTD 為 XML 文檔編寫樣式單,編寫處理程序,這樣可以有效地提高工作效率。

    • 使用 DTD 可以驗(yàn)證數(shù)據(jù)的有效性。

    DTD 對(duì)文檔的邏輯結(jié)構(gòu)進(jìn)行了約束,這種約束可以比較寬松,也可以十分嚴(yán)格。可以根據(jù) DTD 檢查數(shù)據(jù),以驗(yàn)證其是否符合規(guī)定和要求,這可以保證數(shù)據(jù)的正確和有效。

    DTD 主要定義方式:

    (1)內(nèi)部定義法,DTD 文件放在 XML 文件內(nèi)部。

    <!DOCTYPE 根元素 [元素聲明]>

    請(qǐng)看下面的例子,book.xml:

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE bookstore [ <!ELEMENT bookstore (book+)> <!ELEMENT book (bookname,author,price)> <!ATTLIST book id CDATA #REQUIRED> <!ELEMENT bookname (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ELEMENT price (#PCDATA)> ]> <bookstore> <book> <bookname>帶你飛培訓(xùn)教程</bookname> <author>huangjinjin</author> <price>1.00元</price> </book> <book> <bookname>降龍十八講秘籍</bookname> <author>洪七公</author> <price>0.01元</price> </book> </bookstore>

    (2)外部定義,請(qǐng)看下面這個(gè)例子。

    bookstore.dtd:

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE bookstore [ <!ELEMENT bookstore (book+)> <!ELEMENT book (bookname,author,price)> <!ATTLIST book id CDATA #REQUIRED> <!ELEMENT bookname (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ELEMENT price (#PCDATA)> ]>

    book.xml:

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE bookstore SYSTEM "bookstore.dtd"> <bookstore> <book> <bookname>帶你飛培訓(xùn)教程</bookname> <author>huangjinjin</author> <price>1.00元</price> </book> <book> <bookname>降龍十八講秘籍</bookname> <author>洪七公</author> <price>0.01元</price> </book> </bookstore>

    2.XML Schema 約束

    XML Schema 是基于 XML DTD 的替代者,XML Schema 描述 XML 文檔的結(jié)構(gòu)。XML Schema 語(yǔ)言也稱作 XML Schema 定義(XML Schema Definition 簡(jiǎn)稱 XSD)。DTD 不是通過(guò) XML 語(yǔ)法定義文檔結(jié)構(gòu),不能定義數(shù)據(jù)類型和限制;Schema 通過(guò) XML 語(yǔ)法定義文檔結(jié)構(gòu),可以定義數(shù)據(jù)類型和限制。

    XML Schema 對(duì) XML 文件的主要約定有:

    • 定義可出現(xiàn)在 XML 文檔中的元素;
    • 定義可出現(xiàn)在 XML 文檔中的屬性;
    • 定義哪個(gè)元素是子元素;
    • 定義子元素的次序;
    • 定義子元素的數(shù)目;
    • 定義元素是否為空,或者是否可包含文本;
    • 定義元素和屬性的數(shù)據(jù)類型;
    • 定義元素和屬性的默認(rèn)值以及固定值。

    為何使用 Schema,原因有幾下幾點(diǎn):

    • XML Schema 可針對(duì)未來(lái)的需求進(jìn)行擴(kuò)展;
    • XML Schema 更完善,功能更強(qiáng)大;
    • XML Schema 基于 XML 編寫;
    • XML Schema 支持?jǐn)?shù)據(jù)類型和限制;
    • XML Schema 支持命名空間。

    我們看下面這個(gè)例子。

    book.xsd 文件:

    <?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.mybook.org/BookSchema" xmlns:tns="http://www.mybook.org/BookSchema" elementFormDefault="qualified"> <!-- 定義一個(gè)標(biāo)簽 --> <element name="bookstore"> <!-- 復(fù)合類型 就是該標(biāo)簽含有子標(biāo)簽 --> <complexType> <!-- 含有不限定個(gè)數(shù)的子標(biāo)簽 --> <sequence maxOccurs="unbounded"> <!-- 定義一個(gè)子標(biāo)簽 --> <element name="book"> <complexType> <sequence> <!-- 定義一個(gè)文本子標(biāo)簽 --> <element name="bookname" type="string" /> <element name="author" type="string" /> <element name="price" type="string" /> </sequence> <attribute name="id" type="string"></attribute> </complexType> </element> </sequence> </complexType> </element> </schema>

    book.xml

    <?xml version="1.0" encoding="UTF-8" ?> <bookstore xmlns="http://www.w3.org/2001/XMLSchema-instance" xmlns:nsbook="http://www.mybook.org/BookSchema" nsbook:schemaLocation="http://www.mybook.org/BookSchema book.xsd"> <book id="1"> <bookname>帶你飛培訓(xùn)教程</bookname> <author>huangjinjin</author> <price>1.00元</price> </book> <book id="2"> <bookname>降龍十八講秘籍</bookname> <author>洪七公</author> <price>0.01元</price> </book> </bookstore>

    Java 內(nèi)置解析 XML API: DOM、SAX

    DOM

    DOM的全稱是 Document Object Model,即文檔對(duì)象模型,W3C 組織推薦處理 XML 的一種方式。在應(yīng)用程序中,基于 DOM 的 XML 分析器將一個(gè) XML 文檔轉(zhuǎn)換成一個(gè)對(duì)象模型的集合(通常稱 DOM 樹),應(yīng)用程序正是通過(guò)對(duì)這個(gè)對(duì)象模型的操作,來(lái)實(shí)現(xiàn)對(duì) XML 文檔數(shù)據(jù)的操作。通過(guò) DOM 接口,應(yīng)用程序可以在任何時(shí)候訪問(wèn) XML 文檔中的任何一部分?jǐn)?shù)據(jù),因此這種利用 DOM 接口的機(jī)制也被稱作隨機(jī)訪問(wèn)機(jī)制。

    DOM 接口提供了一種通過(guò)分層對(duì)象模型來(lái)訪問(wèn) XML 文檔信息的方式,這些分層對(duì)象模型依據(jù) XML 的文檔結(jié)構(gòu)形成了一棵節(jié)點(diǎn)樹。無(wú)論 XML 文檔中所描述的是什么類型的信息,即便是制表數(shù)據(jù)、項(xiàng)目列表或一個(gè)文檔,利用 DOM 所生成的模型都是節(jié)點(diǎn)樹的形式。也就是說(shuō) DOM 強(qiáng)制使用樹模型來(lái)訪問(wèn) XML 文檔中的信息。由于 XML 本質(zhì)上就是一種分層結(jié)構(gòu),所以這種描述方法是相當(dāng)有效的。

    DOM 樹所提供的隨機(jī)訪問(wèn)方式給應(yīng)用程序的開發(fā)帶來(lái)了很大的靈活性,它可以任意地控制整個(gè) XML 文檔中的內(nèi)容。然而,由于 DOM 分析器把整個(gè) XML 文檔轉(zhuǎn)化成 DOM 樹放在了內(nèi)存中,因此當(dāng)文檔比較大或者結(jié)構(gòu)比較復(fù)雜時(shí),對(duì)內(nèi)存的需求就比較高。而且對(duì)于結(jié)構(gòu)復(fù)雜的樹的遍歷也是一項(xiàng)耗時(shí)的操作。所以 DOM 分析器對(duì)機(jī)器性能的要求比較高,實(shí)現(xiàn)效率不十分理想。不過(guò),由于 DOM 分析器所采用的樹結(jié)構(gòu)的思想與 XML 文檔的結(jié)構(gòu)相吻合,同時(shí)鑒于隨機(jī)訪問(wèn)所帶來(lái)的方便,因此 DOM 分析器還是有很廣泛的使用價(jià)值的。

    其優(yōu)點(diǎn)主要有:

  • 形成了樹結(jié)構(gòu),有助于更好的理解、掌握,且代碼容易編寫。
  • 解析過(guò)程中,樹結(jié)構(gòu)保存在內(nèi)存中,方便修改。
  • 其缺點(diǎn)主要有:

  • 由于文件是一次性讀取,所以對(duì)內(nèi)存的耗費(fèi)比較大。
  • 如果 XML 文件比較大,容易影響解析性能且可能會(huì)造成內(nèi)存溢出。
  • DOM 操作 XML 例子,請(qǐng)見下面代碼:

    // 創(chuàng)建一個(gè)DocumentBuilderFactory的對(duì)象 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // 創(chuàng)建一個(gè)DocumentBuilder的對(duì)象 try { // 創(chuàng)建DocumentBuilder對(duì)象 DocumentBuilder db = dbf.newDocumentBuilder(); // 通過(guò)DocumentBuilder對(duì)象的parser方法加載books.xml文件到當(dāng)前項(xiàng)目下 Document document = db.parse("C:\\Users\\Administrator\\Desktop\\xmlchat\\xml-chat\\src\\test\\resources\\3.xml"); // 獲取所有book節(jié)點(diǎn)的集合 NodeList bookList = document.getElementsByTagName("book"); // 通過(guò)nodelist的getLength()方法可以獲取bookList的長(zhǎng)度 System.out.println("一共有" + bookList.getLength() + "本書"); // 遍歷每一個(gè)book節(jié)點(diǎn) for (int i = 0; i < bookList.getLength(); i++) { System.out.println("=================下面開始遍歷第" + (i + 1) + "本書的內(nèi)容================="); // 通過(guò) item(i)方法 獲取一個(gè)book節(jié)點(diǎn),nodelist的索引值從0開始 Node book = bookList.item(i); // 獲取book節(jié)點(diǎn)的所有屬性集合 NamedNodeMap attrs = book.getAttributes(); System.out.println("第 " + (i + 1) + "本書共有" + attrs.getLength() + "個(gè)屬性"); // 遍歷book的屬性 for (int j = 0; j < attrs.getLength(); j++) { // 通過(guò)item(index)方法獲取book節(jié)點(diǎn)的某一個(gè)屬性 Node attr = attrs.item(j); // 獲取屬性名 值 System.out.print("屬性名:" + attr.getNodeName()+", 屬性值" + attr.getNodeValue()); } // 解析book節(jié)點(diǎn)的子節(jié)點(diǎn) NodeList childNodes = book.getChildNodes(); // 遍歷childNodes獲取每個(gè)節(jié)點(diǎn)的節(jié)點(diǎn)名和節(jié)點(diǎn)值 System.out.println("第" + (i + 1) + "本書共有" + childNodes.getLength() + "個(gè)子節(jié)點(diǎn)"); for (int k = 0; k < childNodes.getLength(); k++) { // 區(qū)分出text類型的node以及element類型的node if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) { // 獲取了element類型節(jié)點(diǎn)的節(jié)點(diǎn)名 System.out.print("第" + (k + 1) + "個(gè)節(jié)點(diǎn)的節(jié)點(diǎn)名:" + childNodes.item(k).getNodeName()); // 獲取了element類型節(jié)點(diǎn)的節(jié)點(diǎn)值 System.out.println("--節(jié)點(diǎn)值是:" + childNodes.item(k).getFirstChild().getNodeValue()); } } System.out.println("======================結(jié)束遍歷第" + (i + 1) + "本書的內(nèi)容================="); } } catch (Exception e) { e.printStackTrace(); }

    SAX

    SAX 的全稱是 Simple APIs for XML,即 XML 簡(jiǎn)單應(yīng)用程序接口。與 DOM 不同,SAX 提供的訪問(wèn)模式是一種順序模式,這是一種快速讀寫 XML 數(shù)據(jù)的方式。當(dāng)使用 SAX 分析器對(duì) XML 文檔進(jìn)行分析時(shí),會(huì)觸發(fā)一系列事件,并激活相應(yīng)的事件處理函數(shù),應(yīng)用程序通過(guò)這些事件處理函數(shù)實(shí)現(xiàn)對(duì) XML 文檔的訪問(wèn),因而 SAX 接口也被稱作事件驅(qū)動(dòng)接口。SAX 不是官方標(biāo)準(zhǔn),但它是 XML 社區(qū)事實(shí)上的標(biāo)準(zhǔn),幾乎所有的 XML 解析器都支持它。

    其優(yōu)點(diǎn)主要有:

  • 采用事件驅(qū)動(dòng)模式,對(duì)內(nèi)存耗費(fèi)比較小。
  • 適用于只處理 XML 文件中的數(shù)據(jù)時(shí)。
  • 其缺點(diǎn)主要有:

  • 編碼比較麻煩。
  • 很難同時(shí)訪問(wèn) XML 文件中的多處不同數(shù)據(jù)。
  • SAX 處理 XML 例子,請(qǐng)見下面代碼:

    // 獲取Sax解析工程對(duì)象 SAXParserFactory factory = SAXParserFactory.newInstance(); try { SAXParser parser = factory.newSAXParser(); // 新建xml處理器 SAXParserHandler handler = new SAXParserHandler(); parser.parse("C:\\Users\\Administrator\\Desktop\\xmlchat\\xml-chat\\src\\test\\resources\\3.xml", handler); System.out.println("共有" + handler.getBookList().size() + "本書"); for (Book book : handler.getBookList()) { System.out.println(book.getId()); System.out.println(book.getBookname()); System.out.println(book.getAuthor()); System.out.println(book.getPrice()); } } catch (Exception e) { e.printStackTrace(); }

    XML 處理器 SAXParserHandler 關(guān)鍵代碼,如下:

    /** * 解析xml元素 */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 調(diào)用DefaultHandler類的startElement方法 super.startElement(uri, localName, qName, attributes); if (qName.equals("book")) { bookIndex++; // 創(chuàng)建一個(gè)book對(duì)象 book = new Book(); // 開始解析book元素的屬性 System.out.println("============開始遍歷某一本書的內(nèi)容================="); // 不知道book元素下屬性的名稱以及個(gè)數(shù),如何獲取屬性名以及屬性值 int num = attributes.getLength(); for (int i = 0; i < num; i++) { System.out.print("book元素的第" + (i + 1) + "個(gè)屬性名是:" + attributes.getQName(i)); System.out.println(", 屬性值是:" + attributes.getValue(i)); if (attributes.getQName(i).equals("id")) { book.setId(attributes.getValue(i)); } } } else { System.out.print("節(jié)點(diǎn)名是:" + qName +", "); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { // 調(diào)用DefaultHandler類的endElement方法 super.endElement(uri, localName, qName); // 判斷是否針對(duì)一本書已經(jīng)遍歷結(jié)束 if (qName.equals("book")) { bookList.add(book); book = null; System.out.println("===========結(jié)束遍歷某一本書的內(nèi)容================="); } else if (qName.equals("bookname")) { book.setBookname(value); } else if (qName.equals("author")) { book.setAuthor(value); } else if (qName.equals("price")) { book.setPrice(value); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); value = new String(ch, start, length); if (!value.trim().equals("")) { System.out.println("節(jié)點(diǎn)值是:" + value); } }

    XML 解析框架 JDOM

    JDOM 目的是成為 Java 特定文檔模型,簡(jiǎn)化與 XML 的交互并且比使用 DOM 實(shí)現(xiàn)更快。由于是第一個(gè) Java 特定模型,所以 JDOM 一直得到大力推廣和促進(jìn)。正在考慮通過(guò)“Java 規(guī)范請(qǐng)求 JSR-102”將它最終用作“Java 標(biāo)準(zhǔn)擴(kuò)展”。從2000年初就已經(jīng)開始了 JDOM 開發(fā)。JDOM 與 DOM 主要有兩方面不同。第一,JDOM 僅使用具體類而不使用接口,這在某些方面簡(jiǎn)化了 API,但是也限制了靈活性;第二,API 大量使用了 Collections 類,簡(jiǎn)化了那些已經(jīng)熟悉這些類的 Java 開發(fā)者的使用。

    JDOM 文檔聲明其目的是“使用20%(或更少)的精力解決80%(或更多)Java/XML 問(wèn)題”。JDOM 對(duì)于大多數(shù) Java/XML 應(yīng)用程序來(lái)說(shuō)非常有用,并且大多數(shù)開發(fā)者發(fā)現(xiàn) API 比 DOM 容易理解得多。JDOM 還包括對(duì)程序行為的相當(dāng)廣泛檢查以防止用戶做任何在 XML 中無(wú)意義的事。然而它仍需要您充分理解 XML 以便做一些超出基本的工作(或者甚至理解某些情況下的錯(cuò)誤)。這也許是比學(xué)習(xí) DOM 或 JDOM 接口都更有意義的工作。JDOM 自身不包含解析器。它通常使用 SAX2 解析器來(lái)解析和驗(yàn)證輸入 XML 文檔,盡管它還可以將以前構(gòu)造的 DOM 表示作為輸入。它包含一些轉(zhuǎn)換器以將 JDOM 表示輸出成 SAX2 事件流、DOM 模型或 XML 文本文檔。JDOM 是在 Apache 許可證變體下發(fā)布的開放源碼。同時(shí)需要注意的是 JDOM 目前分為兩個(gè)版本,分別為JDOM 1.x 和 JDOM 2.x。

    其主要特征有:

  • 僅使用具體類,而不使用接口。
  • API 大量使用了 Collections 類。
  • JDOM 解析 XML 的例子,如下:

    import java.io.File; import java.io.FileInputStream; import java.util.List; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.input.SAXBuilder; public class JDomTest { public static void main(String[] args) { try { // 創(chuàng)建一個(gè)SAXBuilder對(duì)象 SAXBuilder sb = new SAXBuilder(); File file = new File("C:\\Users\\Administrator\\Desktop\\xmlchat\\xml-chat\\src\\test\\resources\\1.xml"); FileInputStream in = new FileInputStream(file); // 構(gòu)造文檔對(duì)象 Document doc = sb.build(in); // 獲取根元素bookstore Element root = doc.getRootElement(); // 取名字為book的所有元素 List<Element> books = root.getChildren("book"); for (int i = 0; i < books.size(); i++) { Element e = books.get(i); List<Element> sube = e.getChildren(); System.out.println("第" + (i + 1) + "本書信息:"); e = sube.get(0); System.out.println(e.getName() + "=" + e.getText()); e = sube.get(1); System.out.println(e.getName() + "=" + e.getText()); e = sube.get(2); System.out.println(e.getName() + "=" + e.getText()); } } catch (Exception e) { e.printStackTrace(); } } }

    XML 解析框架 DOM4J

    雖然 DOM4J 代表了完全獨(dú)立的開發(fā)結(jié)果,但最初它是 JDOM 的一種智能分支。它合并了許多超出基本 XML 文檔表示的功能,包括集成的 XPath 支持、 XML Schema 支持以及用于大文檔或流化文檔的基于事件的處理。它還提供了構(gòu)建文檔表示的選項(xiàng),它通過(guò) DOM4J API 和標(biāo)準(zhǔn) DOM 接口具有并行訪問(wèn)功能。

    為支持所有這些功能,DOM4J 使用接口和抽象基本類方法。DOM4J 大量使用了 API 中的 Collections 類,但是在許多情況下,它還提供一些替代方法以允許更好的性能或更直接的編碼方法。直接好處是,雖然 DOM4J 付出了更復(fù)雜的 API 的代價(jià),但是它提供了比 JDOM 大得多的靈活性。在添加靈活性、XPath 集成和對(duì)大文檔處理的目標(biāo)時(shí),DOM4J 的目標(biāo)與 JDOM 是一樣的:針對(duì) Java 開發(fā)者的易用性和直觀操作。它還致力于成為比 JDOM 更完整的解決方案,實(shí)現(xiàn)在本質(zhì)上處理所有 Java/XML 問(wèn)題的目標(biāo)。在完成該目標(biāo)時(shí),它比 JDOM 更少?gòu)?qiáng)調(diào)防止不正確的應(yīng)用程序行為。

    DOM4J 是一個(gè)非常非常優(yōu)秀的 Java XML API,具有性能優(yōu)異、功能強(qiáng)大和極端易用使用的特點(diǎn),同時(shí)它也是一個(gè)開放源代碼的軟件。如今你可以看到越來(lái)越多的 Java 軟件都在使用 DOM4J 來(lái)讀寫 XML,特別值得一提的是 Sun 的 JAXM 也在用 DOM4J。同時(shí)需要注意的是 DOM4J 目前也分為兩個(gè)版本,分別為 DOM4J 1.x和 DOM4J 2.x。

    其特征主要有:

  • JDOM 的一種智能分支,它合并了許多超出基本 XML 文檔表示的功能。
  • 它使用接口和抽象基本類方法。
  • 具有性能優(yōu)異、靈活性好、功能強(qiáng)大和極端易用的特點(diǎn)。
  • 是一個(gè)開放源碼的文件。
  • DOM4J 解析 XML 的例子,如下:

    import java.io.File; import java.util.Iterator; import java.util.List; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class DOM4JTest { public static void main(String[] args) { try { // 創(chuàng)建SAXReader的對(duì)象reader SAXReader reader = new SAXReader(); // 通過(guò)reader對(duì)象的read方法加載books.xml文件,獲取docuemnt對(duì)象。 Document document = reader.read( new File("C:\\Users\\Administrator\\Desktop\\xmlchat\\xml-chat\\src\\test\\resources\\1.xml")); // 通過(guò)document對(duì)象獲取根節(jié)點(diǎn)bookstore Element element = document.getRootElement(); // 通過(guò)element對(duì)象的elementIterator方法獲取迭代器 Iterator<Element> iter = element.elementIterator(); int index = 0; // 遍歷迭代器,獲取根節(jié)點(diǎn)中的信息(書籍) while (iter.hasNext()) { Element e = iter.next(); System.out.println("第" + (index + 1) + "本書"); List<Attribute> bookAttrs = e.attributes(); for (Attribute attr : bookAttrs) { System.out.println("屬性名:" + attr.getName() + ",屬性值:" + attr.getValue()); } index = index + 1; Iterator<Element> siter = e.elementIterator(); while (siter.hasNext()) { e = siter.next(); System.out.println(e.getName() + "=" + e.getStringValue()); } } } catch (Exception e) { e.printStackTrace(); } } }

    XML解析框架 XStream

    XStream 是一種 OXMapping 技術(shù),是用來(lái)處理 XML 文件序列化的框架,將 JavaBean 序列化或?qū)?XML 文件反序列化,不需要其它輔助類和映射文件,使得 XML 序列化不再繁索。另外,Xstream 也可以將 JavaBean 序列化成 Json 或反序列化,使用非常方便。Java 自帶的 JAXB(Java Architecture for XML Binding) API 也有相應(yīng)的功能。下面分別介紹下這兩種 API 的使用方法。

    JAXB 介紹

    JAXB 相關(guān)的重要 Class 和 Interface 有:

    • JAXBContext 類,是應(yīng)用的入口,用于管理 XML/Java 綁定信息。
    • Marshaller 接口,將 Java 對(duì)象序列化為 XML 數(shù)據(jù)。
    • Unmarshaller 接口,將 XML 數(shù)據(jù)反序列化為 Java 對(duì)象。

    JDK 中 JAXB 相關(guān)的重要 Annotation有:

    • @XmlType,將 Java 類或枚舉類型映射到 XML 模式類型。
    • @XmlAccessorType(XmlAccessType.FIELD),控制字段或?qū)傩缘男蛄谢IELD 表示 JAXB 將自動(dòng)綁定 Java 類中的每個(gè)非靜態(tài)的(static)、非瞬態(tài)的(由 @XmlTransient 標(biāo)注)字段到 XML。其他值還有 XmlAccessType.PROPERTY 和 XmlAccessType.NONE。
    • @XmlAccessorOrder,控制 JAXB 綁定類中屬性和字段的排序。
    • @XmlJavaTypeAdapter,使用定制的適配器(即擴(kuò)展抽象類 XmlAdapter 并覆蓋 marshal()和 unmarshal()方法),以序列化 Java 類為 XML。
    • @XmlElementWrapper,對(duì)于數(shù)組或集合(即包含多個(gè)元素的成員變量),生成一個(gè)包裝該數(shù)組或集合的 XML 元素(稱為包裝器)。
    • @XmlRootElement,將 Java 類或枚舉類型映射到 XML 元素。
    • @XmlElement,將 Java 類的一個(gè)屬性映射到與屬性同名的一個(gè) XML 元素。
    • @XmlAttribute,將 Java 類的一個(gè)屬性映射到與屬性同名的一個(gè) XML 屬性。

    注意以下幾點(diǎn):

    • 對(duì)于要序列化(marshal)為 XML 的 Java 類,絕不能把成員變量聲明為 public,否則運(yùn)行將拋出異常 com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException。
    • 對(duì)于 JAXB 相關(guān)的重要 Annotation 的聲明,如 @Xml.....,可以放在成員變量的 setter() 或 getter() 方法上,兩者中任選其一即可,但決不能放在成員變量上,否則運(yùn)行將拋出異常 com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException。

    我們看一個(gè)例子,Book2.java 對(duì)象:

    import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Book2 { private String id; private String bookname; private String author; private String price; public String getId() { return id; } @XmlAttribute public void setId(String id) { this.id = id; } public String getBookname() { return bookname; } @XmlElement public void setBookname(String bookname) { this.bookname = bookname; } public String getAuthor() { return author; } @XmlElement public void setAuthor(String author) { this.author = author; } public String getPrice() { return price; } @XmlElement public void setPrice(String price) { this.price = price; } }

    將 JavaBean 轉(zhuǎn)成 XML,如下:

    import java.io.FileOutputStream; import java.io.StringWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; //將java bean轉(zhuǎn)成xml public class JaxbMarshal { public static void main(String[] args) { try { Book2 book = new Book2(); book.setId("1"); book.setAuthor("千年老二"); book.setBookname("葵花寶典"); book.setPrice("1234"); JAXBContext context = JAXBContext.newInstance(Book2.class); Marshaller m = context.createMarshaller(); StringWriter sw = new StringWriter(); m.marshal(book, sw); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);// 是否格式化 m.marshal(book, new FileOutputStream("src/main/java/book.xml")); System.out.println(sw.toString()); } catch (Exception e) { e.printStackTrace(); } } }

    將 XML 轉(zhuǎn)成 JavaBean,如下:

    import java.io.File; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; //將xml轉(zhuǎn)成java bean public class JaxbUnMarshal { public static void main(String[] args) { try { JAXBContext context = JAXBContext.newInstance(Book2.class); Unmarshaller m = context.createUnmarshaller(); Book2 book = (Book2)m.unmarshal(new File("src/main/java/book.xml")); System.out.println(book.getId()); System.out.println(book.getBookname()); System.out.println(book.getAuthor()); System.out.println(book.getPrice()); } catch (Exception e) { e.printStackTrace(); } } }

    XStream 介紹

    XStream 是個(gè)很強(qiáng)大的工具,能將 Java 對(duì)象和 XML 之間相互轉(zhuǎn)化。XStream 不在意 Java 類中成員變量是私有還是公有,也不在乎是否有默認(rèn)構(gòu)造函數(shù)。它調(diào)用方式也非常簡(jiǎn)單:從 XML 對(duì)象轉(zhuǎn)化為 Java 對(duì)象,使用 fromXML() 方法;從 Java 對(duì)象序列化為 XML,toXML() 即可,很方便。XStream 也支持注解方式,這些都是為了簡(jiǎn)化輸出而設(shè)計(jì)。

    XStream常用注解說(shuō)明有:

    • @XStreamAlias 注解可在類與屬性上,設(shè)置別名;
    • @XStreamAliasType 注解設(shè)置在類,設(shè)置類型別名;
    • @XStreamAsAttribute 注解設(shè)置在屬性上,作用是將類內(nèi)成員作為父節(jié)點(diǎn)屬性輸出;
    • @XStreamConverter 注解設(shè)置在屬性上,注入轉(zhuǎn)化器;
    • @XStreamConverters 注解設(shè)置在屬性上,注入多個(gè)轉(zhuǎn)化器;
    • @XStreamImplicit 常用在集合屬性上,表明只把集合里的元素列序號(hào)到 XML中;
    • @XStreamInclude
    • @XStreamOmitField 注解可設(shè)置在屬性上,表明該屬性不會(huì)被序列化到 XML 中。

    接下來(lái),我們看下 XStream 使用例子。

    Person 實(shí)體類,如下:

    import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAliasType; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamOmitField; @XStreamAliasType("p") public class Person { @XStreamAsAttribute private int id; @XStreamAlias("n") private String name; @XStreamAlias("a") @XStreamOmitField private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }

    XStream 操作 XML,如下:

    import com.thoughtworks.xstream.XStream; public class XStreamTest { public static void main(String[] args) { Person person=new Person(); person.setName("獨(dú)孤求敗"); person.setAge(100); XStream xstream = new XStream(); // 進(jìn)行注解的檢測(cè) 如果沒(méi)有這行注解將不起作用 xstream.autodetectAnnotations(true); //XML序列化 String xml = xstream.toXML(person); System.out.println(xml); //XML反序列化 Person person1=(Person)xstream.fromXML(xml); System.out.println(person1.getName()); System.out.println(person1.getAge()); } }

    備注: xstream.autodetectAnnotations(true) 的作用是開啟注解掃描,如果沒(méi)有改行代碼,默認(rèn)為 false,不開啟注解掃描,這樣的話 Person.java 將不起任何作用。

    總結(jié)

    我們綜合看下 DMO、SAX 和 JDOM 三者之間的區(qū)別。

    (1)DOM:拉模型,把整個(gè)文檔加載到內(nèi)存中。

    • 優(yōu)點(diǎn):整個(gè)文檔樹在內(nèi)存中,便于操作;支持刪除、修改、重新排列等多種功能;
    • 缺點(diǎn):將整個(gè)文檔調(diào)入內(nèi)存(包括無(wú)用的節(jié)點(diǎn)),浪費(fèi)時(shí)間和空間;
    • 使用場(chǎng)合:一旦解析了文檔還需多次訪問(wèn)這些數(shù)據(jù);硬件資源充足(內(nèi)存、CPU)。

    (2)SAX:推模型,事件驅(qū)動(dòng)編程,基于回調(diào) SAX ,事件驅(qū)動(dòng)。當(dāng)解析器發(fā)現(xiàn)元素開始、元素結(jié)束、文本、文檔的開始或結(jié)束等時(shí),發(fā)送事件,程序員編寫響應(yīng)這些事件的代碼,保存數(shù)據(jù)。

    • 優(yōu)點(diǎn):不用事先調(diào)入整個(gè)文檔,占用資源少;
    • 缺點(diǎn):不是持久的;事件過(guò)后,若沒(méi)保存數(shù)據(jù),那么數(shù)據(jù)就丟了;無(wú)狀態(tài)性;從事件中只能得到文本,但不知該文本屬于哪個(gè)元素;
    • 使用場(chǎng)合:數(shù)據(jù)量較大的XML文檔,占用內(nèi)存高,機(jī)器內(nèi)存少,無(wú)法一次加載XML到內(nèi)存;只需XML文檔的少量?jī)?nèi)容,很少回頭訪問(wèn);

    (3)JDOM:為減少 DOM、SAX 的編碼量,出現(xiàn)了 JDOM。

    • 優(yōu)點(diǎn):20-80原則,極大減少了代碼量,提供常用 API 減少重復(fù)勞動(dòng);
    • 使用場(chǎng)合:要實(shí)現(xiàn)的功能簡(jiǎn)單,如解析、創(chuàng)建等Java程序。

    再來(lái)看下三者之間的性能比較。

    (1)DOM4J 性能最好,連 Sun 的 JAXM 也在用 DOM4J。目前許多開源項(xiàng)目中大量采用 DOM4J,例如大名鼎鼎的 Hibernate 也用 DOM4J 來(lái)讀取 XML 配置文件。如果不考慮可移植性,那就采用 DOM4J。

    (2)JDOM 和 DOM 在性能測(cè)試時(shí)表現(xiàn)不佳,在測(cè)試 10M 文檔時(shí)內(nèi)存溢出。在小文檔情況下還值得考慮使用 DOM 和 JDOM。雖然 JDOM 的開發(fā)者已經(jīng)說(shuō)明 他們期望在正式發(fā)行版前專注性能問(wèn)題,但是從性能觀點(diǎn)來(lái)看,它確實(shí)沒(méi)有值得推薦之處。另外,DOM 仍是一個(gè)非常好的選擇。DOM 實(shí)現(xiàn)廣泛應(yīng)用于多種編程語(yǔ)言。它還是許多其它與 XML 相關(guān)的標(biāo)準(zhǔn)的基礎(chǔ),因?yàn)樗将@得 W3C 推薦(與基于非標(biāo)準(zhǔn)的 Java 模型相對(duì)),所以在某些類型的項(xiàng)目中可能也需要它(如在 JavaScript 中使用 DOM)。

    (3)SAX 表現(xiàn)較好,這要依賴于它特定的解析方式——事件驅(qū)動(dòng)。一個(gè) SAX 檢測(cè)即將到來(lái)的 XML 流,但并沒(méi)有載入到內(nèi)存(當(dāng)然當(dāng) XML 流被讀入時(shí),會(huì)有部分文檔暫時(shí)隱藏在內(nèi)存中)。

    這里提供下源碼地址:https://gitee.com/hjj520/xml,大家可以自行下載學(xué)習(xí)。


    本文首發(fā)于GitChat,未經(jīng)授權(quán)不得轉(zhuǎn)載,轉(zhuǎn)載需與GitChat聯(lián)系。

    閱讀全文: http://gitbook.cn/gitchat/activity/5aa3ab85291bf90af9b04b2c

    您還可以下載 CSDN 旗下精品原創(chuàng)內(nèi)容社區(qū) GitChat App , GitChat 專享技術(shù)內(nèi)容哦。

    總結(jié)

    以上是生活随笔為你收集整理的常用 XML 解析技术的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。