原帖地址:http://www.ibm.com/developerworks/cn/xml/x-stax1.html

2007 年 3 月 02 日

Streaming API for XML (StAX) 是用 Java™ 語(yǔ)言處理 XML 的最新標(biāo)準(zhǔn)。作為一種面向流的方法,無(wú)論從性能還是可用性上都優(yōu)于其他方法,如 DOM 和 SAX。本系列分為 3 部分,本文是第 1 部分,簡(jiǎn)要介紹了 StAX 及其處理 XML 的基于指針的 API。

StAX 概述

從一開(kāi)始,Java API for XML Processing (JAXP) 就提供了兩種方法來(lái)處理 XML:文檔對(duì)象模型(DOM)方法是用標(biāo)準(zhǔn)的對(duì)象模型表示 XML 文檔;Simple API for XML (SAX) 方法使用應(yīng)用程序提供的事件處理程序來(lái)處理 XML。JSR-173 提出了一種面向流的新方法:Streaming API for XML (StAX)。其最終版本于 2004 年 3 月發(fā)布,并成為了 JAXP 1.4(將包含在即將發(fā)布的 Java 6 中)的一部分。

如其名稱所暗示的那樣,StAX 把重點(diǎn)放在上。實(shí)際上,StAX 與其他方法的區(qū)別就在于應(yīng)用程序能夠把 XML 作為一個(gè)事件流來(lái)處理。將 XML 作為一組事件來(lái)處理的想法并不新穎(事實(shí)上 SAX 已經(jīng)提出來(lái)了),但不同之處在于 StAX 允許應(yīng)用程序代碼把這些事件逐個(gè)拉出來(lái),而不用提供在解析器方便時(shí)從解析器中接收事件的處理程序。

StAX 實(shí)際上包括兩套處理 XML 的 API,分別提供了不同程度的抽象。基于指針的 API 允許應(yīng)用程序把 XML 作為一個(gè)標(biāo)記(或事件)流來(lái)處理;應(yīng)用程序可以檢查解析器的狀態(tài),獲得解析的上一個(gè)標(biāo)記的信息,然后再處理下一個(gè)標(biāo)記,依此類推。這是一種低層 API,盡管效率高,但是沒(méi)有提供底層 XML 結(jié)構(gòu)的抽象。較為高級(jí)的基于迭代器的 API 允許應(yīng)用程序把 XML 作為一系列事件對(duì)象來(lái)處理,每個(gè)對(duì)象和應(yīng)用程序交換 XML 結(jié)構(gòu)的一部分。應(yīng)用程序只需要確定解析事件的類型,將其轉(zhuǎn)換成對(duì)應(yīng)的具體類型,然后利用其方法獲得屬于該事件的信息。





回頁(yè)首


基本原理

為了使用這兩類 API,應(yīng)用程序首先必須獲得一個(gè)具體的 XMLInputFactory。根據(jù)傳統(tǒng)的 JAXP 風(fēng)格,要用到抽象工廠模式;XMLInputFactory 類提供了靜態(tài)的 newInstance 方法,它負(fù)責(zé)定位和實(shí)例化具體的工廠。配置該實(shí)例可設(shè)置定制或者預(yù)先定義好的屬性(其名稱在類 XMLInputFactory 中定義)。最后,為了使用基于指針的 API,應(yīng)用程序還要通過(guò)調(diào)用某個(gè) createXMLStreamReader 方法獲得一個(gè) XMLStreamReader。如果要使用基于事件迭代器的 API,應(yīng)用程序就要調(diào)用 createXMLEventReader 方法獲得一個(gè) XMLEventReader(如清單 1 所示)。


清單 1. 獲取和配置默認(rèn)的 XMLInputFactory
            // get the default factory instance
            XMLInputFactory factory = XMLInputFactory.newInstance();
            // configure it to create readers that coalesce adjacent character sections
            factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
            XMLStreamReader r = factory.createXMLStreamReader(input);
            // ...
            

XMLStreamReaderXMLEventReader 都允許應(yīng)用程序迭代底層的 XML 流。兩種方法的差別在于如何公開(kāi)解析后的 XML InfoSet 信息片段。XMLStreamReader 就像一個(gè)指針,指在剛剛解析過(guò)的 XML 標(biāo)記的后面,并提供了方法獲得更多關(guān)于該標(biāo)記的信息。這種方法節(jié)約內(nèi)存,因?yàn)椴挥脛?chuàng)建新的對(duì)象。但是,業(yè)務(wù)應(yīng)用程序開(kāi)發(fā)人員可能會(huì)發(fā)現(xiàn) XMLEventReader 更直觀一些,因?yàn)樗鼘?shí)際上就是一個(gè)標(biāo)準(zhǔn)的 Java 迭代器,將 XML 變成了事件對(duì)象流。每個(gè)事件對(duì)象都封裝了它所表示的特定 XML 結(jié)構(gòu)固有的信息。本系列的第二部分將詳細(xì)討論這種基于事件迭代器的 API。

使用哪種風(fēng)格的 API 取決于具體情況。和基于指針的 API 相比,基于事件迭代器的 API 具有更多的面向?qū)ο筇卣鳌R虼烁阌趹?yīng)用于模塊化的體系結(jié)構(gòu),因?yàn)楫?dāng)前的解析器狀態(tài)反映在事件對(duì)象中,應(yīng)用程序組件在處理事件的時(shí)候不需要訪問(wèn)解析器/讀取器。此外,還可以使用 XMLInputFactorycreateXMLEventReader(XMLStreamReader) 方法從 XMLStreamReader 創(chuàng)建 XMLEventReader

StAX 還定義了一種序列化器 API,Java 標(biāo)準(zhǔn) XML 處理支持中一直缺少的一種特性。和解析一樣,也包含兩種風(fēng)格的流式 API:處理標(biāo)記的底層 XMLStreamWriter 和處理事件對(duì)象的高層 XMLEventWriterXMLStreamWriter 提供了寫(xiě)入單個(gè) XML 記號(hào)(比如開(kāi)始和關(guān)閉標(biāo)記或者元素屬性)的方法,不檢查這些標(biāo)記是否格式良好。另一方面,XMLEventWriter 允許應(yīng)用程序向輸出中添加完整的 XML 事件。第 3 部分將詳細(xì)討論 StAX 序列化器 API。

為什么使用 StAX?

開(kāi)始學(xué)習(xí)一種新的處理 XML 的 API 之前,可能要問(wèn)是否值得這樣做。事實(shí)上,StAX 所采用的基于拉的方法和其他方法相比有一些突出的優(yōu)點(diǎn)。首先,不管使用哪種 API 風(fēng)格,都是應(yīng)用程序調(diào)用讀取器(解析器)而不是相反。通過(guò)保留解析過(guò)程的控制權(quán),可以簡(jiǎn)化調(diào)用代碼來(lái)準(zhǔn)確地處理它預(yù)期的內(nèi)容。或者發(fā)生意外時(shí)停止解析。此外,由于該方法不基于處理程序回調(diào),應(yīng)用程序不需要像使用 SAX 那樣模擬解析器的狀態(tài)。

StAX 仍然保留了 SAX 相對(duì)于 DOM 的優(yōu)點(diǎn)。通過(guò)把重心從結(jié)果對(duì)象模型轉(zhuǎn)移到解析流本身,從理論上說(shuō)應(yīng)用程序能夠處理無(wú)限的 XML 流,因?yàn)槭录逃械呐R時(shí)性,不會(huì)在內(nèi)存中累積起來(lái)。對(duì)于那些使用 XML 作為消息傳遞協(xié)議而非表示文檔內(nèi)容的那些應(yīng)用程序尤其重要,比如 Web 服務(wù)或即時(shí)消息應(yīng)用程序。比方說(shuō),如果只是將其轉(zhuǎn)換成特定于應(yīng)用程序的對(duì)象模型然后就將其丟棄,那么為 Web 服務(wù)路由器 servlet 提供一個(gè) DOM 就沒(méi)有多少用處。使用 StAX 直接轉(zhuǎn)化成應(yīng)用程序模型效率更高。對(duì)于 Extensible Messaging and Presence Protocol(XMPP)客戶機(jī),根本不能使用 DOM,因?yàn)?XMPP 客戶機(jī)/服務(wù)器流是隨著用戶輸入的消息實(shí)時(shí)生成。等待流的關(guān)閉標(biāo)簽(以便最終建立 DOM)就意味著等待整個(gè)會(huì)話結(jié)束。通過(guò)把 XML 作為一系列的事件來(lái)處理,應(yīng)用程序能夠以最合適的方式響應(yīng)每個(gè)事件(比如顯示收到的即時(shí)消息等等)。

由于其雙向性,StAX 也支持鏈?zhǔn)教幚恚貏e是在事件層上。接收事件(無(wú)論什么來(lái)源)的能力被封裝在 XMLEventConsumer(XMLEventWriter 的擴(kuò)展)接口中。因此,可以模塊化地編寫(xiě)應(yīng)用程序從 XMLEventReader(也是一個(gè)普通的迭代器,可以按迭代器處理)讀取和處理 XML 事件、然后傳遞給事件消費(fèi)者(如果需要可以進(jìn)一步擴(kuò)展處理鏈)。在第 2 部分將看到,也可使用應(yīng)用程序提供的篩選器(實(shí)現(xiàn)了 EventFilter 接口的類)來(lái)定制 XMLEventReader 或者使用 EventReaderDelegate 修飾已有的 XMLEventReader。

總而言之,和 DOM 以及 SAX 相比,StAX 使應(yīng)用程序更貼近底層的 XML。使用 StAX,應(yīng)用程序不僅可以建立需要的對(duì)象模型(而不需要處理標(biāo)準(zhǔn) DOM),而且可以隨時(shí)這樣做,而不必等到解析器回調(diào)。

下一節(jié)將深入討論基于指針的 API 以及如何有效地使用它處理 XML 流。





回頁(yè)首


基于指針的 API

如果使用基于指針的 API,應(yīng)用程序通過(guò)在 XML 標(biāo)記流中移動(dòng)邏輯指針來(lái)處理 XML。基于指針的解析器實(shí)質(zhì)上是一個(gè)狀態(tài)機(jī),在事件的驅(qū)動(dòng)下從一個(gè)良好定義的狀態(tài)轉(zhuǎn)移到另一個(gè)狀態(tài)。這里的觸發(fā)事件是隨著應(yīng)用程序使用適當(dāng)?shù)姆椒ㄍ苿?dòng)解析器在標(biāo)記流中前進(jìn)而解析出來(lái)的 XML 標(biāo)記。在每個(gè)狀態(tài),都可使用一組方法獲得上一個(gè)事件的信息。一般來(lái)說(shuō),并非每個(gè)狀態(tài)下都能使用所有的方法。

使用基于指針的方法,應(yīng)用程序首先必須通過(guò)調(diào)用其 createXMLStreamReader 方法從 XMLInputFactory 得到 XMLStreamReader。該方法有多個(gè)版本,支持不同類型的輸入。比方說(shuō),可以創(chuàng)建 XMLStreamReader 解析 plain java.io.InputStreamjava.io.Reader 或者 JAXP Source(javax.xml.transform.Source)。從理論上說(shuō),后一種辦法很容易和其他 JAXP 技術(shù)交互,比如 SAX 和 DOM。


清單 2. 創(chuàng)建 XMLStreamReader 解析 InputStream
            URL url = new URL(uri);
            InputStream input = url.openStream();
            XMLInputFactory factory = XMLInputFactory.newInstance();
            XMLStreamReader r = factory.createXMLStreamReader(uri, input);
            // process the stream
            // ...
            r.close();
            input.close();
            

XMLStreamReader 接口基本上定義了基于指針的 API(雖然標(biāo)記常量在其超類型 XMLStreamConstants 接口中定義)。之所以稱為基于指針,是因?yàn)樽x取器就像是底層標(biāo)記流上的指針。應(yīng)用程序可以沿著標(biāo)記流向前推進(jìn)指針并分析當(dāng)前指針?biāo)谖恢玫臉?biāo)記。

XMLStreamReader 提供了多種方法導(dǎo)航標(biāo)記流。為了確定當(dāng)前指針?biāo)赶虻臉?biāo)記(或事件)的類型,應(yīng)用程序可以調(diào)用 getEventType()。該方法返回接口 XMLStreamConstants 中定義的一個(gè)標(biāo)記常量。移動(dòng)到下一個(gè)標(biāo)記,應(yīng)用程序可以調(diào)用 next()。該方法也返回解析的標(biāo)記的類型,如果接著調(diào)用 getEventType() 則返回的值相同。只有當(dāng)方法 hasNext() 返回 true 時(shí)(就是說(shuō)還有其他標(biāo)記需要解析)才能調(diào)用該方法(以及其他移動(dòng)讀取器的方法)。


清單 3. 使用 XMLStreamReader 處理 XML 的常用模式
            // create an XMLStreamReader
            XMLStreamReader r = ...;
            try {
            int event = r.getEventType();
            while (true) {
            switch (event) {
            case XMLStreamConstants.START_DOCUMENT:
            // add cases for each event of interest
            // ...
            }
            if (!r.hasNext())
            break;
            event = r.next();
            }
            } finally {
            r.close();
            }
            

還與其他幾種方法可以移動(dòng) readernextTag() 方法將跳過(guò)所有的空白、注釋或處理指令,直到遇到 START_ELEMENTEND_ELEMENT。該方法在解析只含元素的內(nèi)容時(shí)很有用,如果在發(fā)現(xiàn)標(biāo)記之前遇到非空白文本(不包括注釋或處理指令),就會(huì)拋出異常。getElementText() 方法返回元素的開(kāi)始和關(guān)閉標(biāo)簽(即 START_ELEMENTEND_ELEMENT)之間的所有文本內(nèi)容。如果遇到嵌套的元素就會(huì)拋出異常。

請(qǐng)注意,這里的 “標(biāo)記” 和 “事件” 可以互換使用。雖然基于指針的 API 的文檔說(shuō)的是事件,但把輸入源看成標(biāo)記流很方便。而且不容易造成混亂,因?yàn)檫€有一整套基于事件的 API(那里的事件是真正的對(duì)象)。不過(guò),XMLStreamReader 的事件本質(zhì)上并非都是標(biāo)記。比方說(shuō),START_DOCUMENTEND_DOCUMENT 事件不需要對(duì)應(yīng)的標(biāo)記。前一個(gè)事件是解析開(kāi)始之前發(fā)生,后者則在沒(méi)有更多解析工作要做的時(shí)候發(fā)生(比如解析完成最后一個(gè)元素的關(guān)閉標(biāo)簽之后,讀取器處于 END_ELEMENT 狀態(tài),但是如果沒(méi)有發(fā)現(xiàn)更多的標(biāo)記需要解析,讀取器就會(huì)切換到 END_DOCUMENT 狀態(tài))。

處理 XML 文檔

在每個(gè)解析器狀態(tài),應(yīng)用程序都可通過(guò)可用的方法獲得相關(guān)信息。比如,無(wú)論當(dāng)前是什么類型的事件,getNamespaceContext()getNamespaceURI() 方法可以獲得當(dāng)前有效的名稱空間上下文和名稱空間 URI。類似的,getLocation() 可以獲得當(dāng)前事件的位置信息。方法 hasName()hasText() 可以分別判斷當(dāng)前事件是否有名稱(比如元素或?qū)傩裕┗蛭谋荆ū热缱址⒆⑨尰?CDATA)。方法 isStartElement()isEndElement()isCharacters()isWhiteSpace() 可以方便地確定當(dāng)前事件的性質(zhì)。最后,方法 require(int, String, String) 可以聲明預(yù)期的解析器狀態(tài);除非當(dāng)前事件是指定的類型,并且本地名和名稱空間(如果給出的話)與當(dāng)前事件匹配,否則該方法將拋出異常。


清單 4. 如果當(dāng)前事件是 START_ELEMENT 使用有關(guān)的屬性方法
            if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) {
            System.out.println("Start Element: " + reader.getName());
            for(int i = 0, n = reader.getAttributeCount(); i < n; ++i) {
            QName name = reader.getAttributeName(i);
            String value = reader.getAttributeValue(i);
            System.out.println("Attribute: " + name + "=" + value);
            }
            }
            

創(chuàng)建之后,XMLStreamReader 將從 START_DOCUMENT 狀態(tài)開(kāi)始(即 getEventType() 返回 START_DOCUMENT)。處理標(biāo)記的時(shí)候應(yīng)考慮到這一點(diǎn)。和迭代器不同,不需要先移動(dòng)指針(使用 next())來(lái)進(jìn)入合法的狀態(tài)。同樣地,當(dāng)讀取器轉(zhuǎn)換到最終狀態(tài) END_DOCUMENT 之后,應(yīng)用程序也不應(yīng)再移動(dòng)它。在這種狀態(tài)下,hasNext() 方法將返回 false。

START_DOCUMENT 事件提供了獲取關(guān)于文檔本身信息的方法,如 getEncoding()getVersion()isStandalone()。應(yīng)用程序也可調(diào)用 getProperty(String) 獲得命名屬性的值,不過(guò)一些屬性僅在特定狀態(tài)做了定義(比方說(shuō),如果當(dāng)前事件是 DTD,則屬性 javax.xml.stream.notationsjavax.xml.stream.entities 分別返回所有的符號(hào)和實(shí)體聲明)。

START_ELEMENTEND_ELEMENT 事件中,可以使用和元素名稱以及名稱空間有關(guān)的方法(如 getName()getLocalName()getPrefix()getNamespaceXXX()),在 START_ELEMENT 事件中還可使用與屬性有關(guān)的方法(getAttributeXXX())。

ATTRIBUTENAMESPACE 也被識(shí)別為獨(dú)立的事件,雖然在解析 典型的 XML 文檔時(shí)不會(huì)用到。但是當(dāng) ATTRIBUTENAMESPACE 節(jié)點(diǎn)作為 XPath 查詢結(jié)果返回時(shí)可以使用。

和基于文本的事件(如 CHARACTERSCDATACOMMENTSPACE),可使用各種 getTextXXX() 方法取得文本。可以分別使用 getPITarget()getPIData() 檢索 PROCESSING_INSTRUCTION 的目標(biāo)和數(shù)據(jù)。ENTITY_REFERENCEDTD 也支持 getText()ENTITY_REFERENCE 還支持 getLocalName()

解析完成后,應(yīng)用程序關(guān)閉讀取器并釋放解析過(guò)程中獲得的資源。請(qǐng)注意這樣并沒(méi)有關(guān)閉底層的輸入源。

清單 5 提供了一個(gè)完整的例子,使用基于指針的 API 處理 XML 文檔。首先取得 XMLInputFactory 的默認(rèn)實(shí)例并創(chuàng)建一個(gè) XMLStreamReader 解析給定的輸入流。然后不斷檢查讀取器的狀態(tài),根據(jù)當(dāng)前事件的類型報(bào)告某些信息(比如在 START_ELEMENT 狀態(tài)下報(bào)告元素名及元素屬性)。最后,遇到 END_DOCUMENT 時(shí)關(guān)閉讀取器。


清單 5. 使用 XMLStreamReader 解析 XML 文檔的完整例子
            XMLInputFactory factory = XMLInputFactory.newInstance();
            XMLStreamReader r = factory.createXMLStreamReader(input);
            try {
            int event = r.getEventType();
            while (true) {
            switch (event) {
            case XMLStreamConstants.START_DOCUMENT:
            out.println("Start Document.");
            break;
            case XMLStreamConstants.START_ELEMENT:
            out.println("Start Element: " + r.getName());
            for(int i = 0, n = r.getAttributeCount(); i < n; ++i)
            out.println("Attribute: " + r.getAttributeName(i)
            + "=" + r.getAttributeValue(i));
            break;
            case XMLStreamConstants.CHARACTERS:
            if (r.isWhiteSpace())
            break;
            out.println("Text: " + r.getText());
            break;
            case XMLStreamConstants.END_ELEMENT:
            out.println("End Element:" + r.getName());
            break;
            case XMLStreamConstants.END_DOCUMENT:
            out.println("End Document.");
            break;
            }
            if (!r.hasNext())
            break;
            event = r.next();
            }
            } finally {
            r.close();
            }
            

XMLStreamReader 的高級(jí)用法

通過(guò)調(diào)用 XMLInputFactory 的帶有基本讀取器的 createFilteredReader 方法和一個(gè)應(yīng)用程序定義的篩選器(即實(shí)現(xiàn) StreamFilter 的類實(shí)例),可以創(chuàng)建篩選過(guò)的 XMLStreamReader。導(dǎo)航篩選過(guò)的讀取器時(shí),讀取器每次移動(dòng)到下一個(gè)標(biāo)記之前都會(huì)詢問(wèn)篩選器。如果篩選器認(rèn)可了當(dāng)前事件,就將其公開(kāi)給篩選過(guò)的讀取器。否則跳過(guò)這個(gè)標(biāo)記并檢查下一個(gè),依此類推。這種方法可以讓開(kāi)發(fā)人員創(chuàng)建一個(gè)僅處理解析內(nèi)容子集的基于指針的 XML 處理程序,并與針對(duì)不同的擴(kuò)展的內(nèi)容模型的篩選器結(jié)合使用。

執(zhí)行更復(fù)雜的流操作,可以創(chuàng)建 StreamReaderDelegate 的子類并重寫(xiě)合適的方法。然后使用這個(gè)子類的實(shí)例包裝基本 XMLStreamReader,從而為應(yīng)用程序提供一個(gè)修改過(guò)的基本 XML 流的視圖。可通過(guò)這種技術(shù)對(duì) XML 流執(zhí)行簡(jiǎn)單的轉(zhuǎn)換,比如篩掉或者替換特定的標(biāo)記,甚至增加新的標(biāo)記。

清單 6 用定制的 StreamReaderDelegate 包裝了基本 XMLStreamReader,重寫(xiě)了 next() 方法來(lái)跳過(guò) COMMENTPROCESSING_INSTRUCTION 事件。使用該讀取器時(shí),應(yīng)用程序不用擔(dān)心會(huì)遇到這種類型的標(biāo)記。


清單 6. 使用定制的 StreamReaderDelegate 篩選注釋和處理指令
            URL url = new URL(uri);
            InputStream input = url.openStream();
            XMLInputFactory f = XMLInputFactory.newInstance();
            XMLStreamReader r = f.createXMLStreamReader(uri, input);
            XMLStreamReader fr = new StreamReaderDelegate(r) {
            public int next() throws XMLStreamException {
            while (true) {
            int event = super.next();
            switch (event) {
            case XMLStreamConstants.COMMENT:
            case XMLStreamConstants.PROCESSING_INSTRUCTION:
            continue;
            default:
            return event;
            }
            }
            }
            };
            try {
            int event = fr.getEventType();
            while (true) {
            switch (event) {
            case XMLStreamConstants.COMMENT:
            case XMLStreamConstants.PROCESSING_INSTRUCTION:
            // this should never happen
            throw new IllegalStateException("Filter failed!");
            default:
            // process XML normally
            }
            if (!fr.hasNext())
            break;
            event = fr.next();
            }
            } finally {
            fr.close();
            }
            input.close();
            





回頁(yè)首


基于指針處理之外的其他技術(shù)

可以看到,基于指針的 API 主要是為了提高效率。所有的狀態(tài)信息可以直接從流讀取器獲得,不需要?jiǎng)?chuàng)建額外的對(duì)象。非常適用于性能和低內(nèi)存占用至關(guān)重要的應(yīng)用程序。

人們?cè)缇驼J(rèn)識(shí)到了拉式 XML 解析的好處。事實(shí)上,StAX 本身源于一種稱為 XML Pull Parsing 的方法。XML Pull Parser API 類似于 StAX 所提供的基于指針的 API,可以通過(guò)分析解析器的狀態(tài)獲得上一個(gè)解析事件的信息,然后移動(dòng)到下一個(gè),依此類推。但沒(méi)有提供基于事件迭代器的 API。這是一種非常輕型的方法,特別適合資源受限的環(huán)境,比如 J2ME。但是,很少有實(shí)現(xiàn)提供企業(yè)級(jí)特性如驗(yàn)證,因此 XML Pull 一直未受到企業(yè) Java 開(kāi)發(fā)人員的關(guān)注。

基于以往拉式解析器實(shí)現(xiàn)的經(jīng)驗(yàn),StAX 的創(chuàng)建者選擇了在基于指針的 API 之外增加一種面向?qū)ο蟮?API。雖然 XMLEventReader 接口看起來(lái)似乎很簡(jiǎn)單,但是基于事件迭代器的方法具有一個(gè)基于指針的方法不具備的重要優(yōu)點(diǎn)。通過(guò)將解析器事件變成一級(jí)對(duì)象,從而讓?xiě)?yīng)用程序可以采用面向?qū)ο蟮姆绞教幚硭鼈儭_@樣做有助于模塊化和不同應(yīng)用程序組件之間的代碼重用。


清單 7. 使用 StAX XMLEventReader 解析 XML
            XMLInputFactory inputFactory = XMLInputFactory.newInstance();
            XMLEventReader reader = inputFactory.createXMLEventReader(input);
            try {
            while (reader.hasNext()) {
            XMLEvent e = reader.nextEvent();
            if (e.isCharacters() && ((Characters) e).isWhiteSpace())
            continue;
            out.println(e);
            }
            } finally {
            reader.close();
            }
            





回頁(yè)首


結(jié)束語(yǔ)

本文介紹了 StAX 及其基于指針的 API。第 2 部分將深入討論事件迭代器 API。



參考資料

學(xué)習(xí)

獲得產(chǎn)品和技術(shù)

討論


關(guān)于作者

 

Peter Nehrer 是一名專長(zhǎng)于基于 Eclipse 的企業(yè)解決方案和 Java EE 應(yīng)用程序的軟件顧問(wèn)。他創(chuàng)建了 Ecliptical Software Inc.,并且是一些和 Eclipse 有關(guān)的開(kāi)放源碼項(xiàng)目的貢獻(xiàn)者。他擁有從馬薩諸塞州大學(xué)阿默斯特校區(qū)獲得的計(jì)算機(jī)科學(xué)碩士學(xué)位。