<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    tory320

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      10 隨筆 :: 0 文章 :: 1 評(píng)論 :: 0 Trackbacks
    JAXP 專述

    Sun 的 Java API for XML 語法分析

    ?

    ?

    未顯示需要 JavaScript 的文檔選項(xiàng)


    ?


    級(jí)別: 初級(jí)

    Brett McLaughlin , Enhydra 策略顧問, Lutris Technologies

    2000 年 11 月 01 日

    這是篇細(xì)探 JAXP,Sun 的 Java API for XML 的文章,幫助解除了有關(guān) JAXP 本質(zhì)和服務(wù)目的的疑惑。本文講解了 JAXP 的基本概念,演示 XML 語法分析為什么需要 JAXP,并顯示如何輕易更改 JAXP 使用的語法分析器。本文還進(jìn)一步講述了 SAX 和 DOM 這兩個(gè)流行的與 JAXP 相關(guān)的 Java 和 XML API。

    Java 和 XML 在每一個(gè)技術(shù)領(lǐng)域都制造了新聞,并且對(duì)于軟件開發(fā)人員來說,似乎是 1999 年和 2000 年最重要的發(fā)展。結(jié)果,Java 和 XML API 的數(shù)量激增。其中兩個(gè)最流行的 DOM 和 SAX 還引起極大興趣,而 JDOM 和數(shù)據(jù)綁定 API 也接踵而來。只透徹理解這些技術(shù)中的一個(gè)或兩個(gè)就是一項(xiàng)艱巨任務(wù),而正確使用所有這些技術(shù)就會(huì)使您成為專家。但在去年,另一個(gè) API 給人留下了深刻印象,它就是 Sun 的 Java API for XML,通常稱為 JAXP。如果考慮到 Sun 在其平臺(tái)上還沒有任何特定于 XML 的產(chǎn)品,那么這個(gè)進(jìn)展就不足為奇。而令人驚奇的是人們對(duì) JAXP 了解的缺乏。多數(shù)使用它的開發(fā)人員在他們所用的這個(gè) API 的概念理解上都有錯(cuò)誤。

    什么是 JAXP?

    本文假設(shè)您有 SAX 和 DOM 的基本知識(shí)。這里實(shí)在沒有足夠篇幅來解釋 SAX、DOM 和 JAXP。如果您是 XML 語法分析的新手,那么可能要通過聯(lián)機(jī)資源閱讀 SAX 和 DOM,或者瀏覽我的書。( 參考資源 一節(jié)中有至 API 和我的書的鏈接。)獲得基本知識(shí)后再看本文會(huì)比較好。





    回頁首


    API 還是抽象?

    在講解代碼之前,介紹一些基本概念很重要。嚴(yán)格地說,JAXP 是 API,但是將其稱為抽象層更準(zhǔn)確。它不提供處理 XML 的新方式,不補(bǔ)充 SAX 或 DOM,也不向 Java 和 XML 處理提供新功能。(如果在這點(diǎn)上理解有誤,則本文正好適合您!)它只是使通過 DOM 和 SAX 處理一些困難任務(wù)更容易。如果在使用 DOM 和 SAX API 時(shí)遇到特定于供應(yīng)商的任務(wù),它還使通過獨(dú)立于供應(yīng)商的方式處理這些任務(wù)成為可能。

    雖然要分別講述所有這些特性,但是真正需要掌握的是:JAXP 不提供語法分析功能 !沒有 SAX、DOM 或另一個(gè) XML 語法分析 API,就 無法分析 XML 語法 。有很多人曾讓我將 DOM、SAX 或 JDOM 與 JAXP 進(jìn)行對(duì)比。但進(jìn)行這些對(duì)比是不可能的,因?yàn)榍叭齻€(gè) API 與 JAXP 的目的完全不同。SAX、DOM 和 JDOM 都分析 XML 語法。而 JAXP 卻提供到達(dá)這些語法分析器和結(jié)果的方式。它自身不提供分析文檔語法的新方法。如果要正確使用 JAXP,則一定要弄清這點(diǎn)。這將使您比其它 XML 開發(fā)人員領(lǐng)先一大截。

    如果仍然懷疑(或認(rèn)為我故弄玄虛),請(qǐng)從 Sun 的 Web 站點(diǎn)下載 JAXP 分發(fā)(請(qǐng)參閱 參考資料 一節(jié)),然后就會(huì)知道基本 JAXP 是什么。在包括的 jar ( jaxp.jar ) 中 只有六個(gè)類 !這個(gè) API 會(huì)有多難哪?所有這些類( javax.xml.parsers 包的一部分)都位于現(xiàn)有語法分析器之上。這些類中的兩個(gè)還用于錯(cuò)誤處理。JAXP 比人們想象的要簡(jiǎn)單得多。那么,為什么還感到困惑哪?





    回頁首


    Sun 的 JAXP 和 Sun 的語法分析器

    JAXP 下載時(shí)包括 Sun 的語法分析器。所有 parser 器類作為 com.sun.xml.parser 包和相關(guān)子包的一部分位于 parser.jar 檔案中。應(yīng)該知道,該語法分析器(代碼名為 Crimson) 是 JAXP 自身的一部分。它是 JAXP 版本的一部分,但不是 JAXP API 的一部分。令人困惑嗎?有一點(diǎn)。換這種方式想想:JDOM 與 Apache Xerces 語法分析器一起提供。該語法分析器不是 JDOM 的一部分,但由 JDOM 使用,所以包括它,以確保 JDOM 可以單獨(dú)使用。JAXP 也是如此,但不象 JDOM 那樣好表達(dá):JAXP 與 Sun 的語法分析器一起提供,以便可以立即使用。但是,很多人將 Sun 的語法分析器中包括的類當(dāng)成 JAXP API 的一部分。例如,新聞組中一個(gè)常見的問題是:“怎樣使用 JAXP 中的 XMLDocument 類?其目的是什么?”這個(gè)答案可有些復(fù)雜。

    首先, com.sun.xml.tree.XMLDocument 類不是 JAXP 的一部分。它是 Sun 語法分析器的一部分。所以,這個(gè)問題從一開始就給人以誤導(dǎo)。其次,JAXP 的整個(gè)意義在于在處理語法分析器時(shí)提供供應(yīng)商獨(dú)立性。使用 JAXP 的同一代碼可以與 Sun 的 XML 語法分析器、Apache 的 Xerces XML 語法分析器和 Oracle 的 XML 語法分析器一起使用。而使用特定于 Sun 的類是個(gè)壞主意。這與 JAXP 的整個(gè)意義相背離。現(xiàn)在看出來這個(gè)問題怎樣混淆概念了嗎?語法分析器和 JAXP 發(fā)行版本(至少是 Sun 的版本)中的 API 被混為一談,開發(fā)人員將其中一個(gè)的類和特性當(dāng)成是另一個(gè)的了,反之亦然。





    回頁首


    舊和新

    關(guān)于 JAXP,最后需要指出的是:使用 JAXP 有一些缺陷。例如,JAXP 只支持 SAX 1.0 和 DOM 第一層規(guī)范。SAX 2.0 從 2000 年 5 月起就完成,DOM 第二層規(guī)范支持甚至在大多數(shù)語法分析器中存在更長(zhǎng)時(shí)間。DOM 第二層規(guī)范還沒有完成,但確實(shí)足夠穩(wěn)定以用于生產(chǎn)。這兩個(gè) API 的新版本都有重大改進(jìn),最明顯的是對(duì) XML 名稱空間的支持。該支持還允許“XML Schema 確認(rèn)”,這個(gè)與 XML 相關(guān)的另一熱門技術(shù)。公平地說,當(dāng) JAXP 發(fā)布 1.0 最終發(fā)行版時(shí),SAX 2.0 和 DOM 第一層規(guī)范都還沒有完成。但是,由于沒有包括這些新版本,確實(shí)為開發(fā)人員帶來很大不便。

    還可以使用 JAXP,但是也可以等待 JAXP 1.1,它支持 SAX 2.0 和 DOM第二層規(guī)范 。否則,將發(fā)現(xiàn),JAXP 提供的優(yōu)點(diǎn)以 SAX 和 DOM 最新版本中的功能為代價(jià),并使應(yīng)用程序更加難以編碼。無論是否等待下一個(gè) JAXP 發(fā)行版,都要留意這個(gè)問題。如果將 JAXP 與語法分析器一起使用,而語法分析器支持的 DOM 和 SAX 版本比 JAXP 支持的要高,則可能會(huì)有類路徑問題。所以,事先留意一下,并且,一旦有 JAXP 1.1,馬上升級(jí)。基本理解 JAXP 之后,讓我們看一下 JAXP 依賴的 API:SAX 和 DOM。





    回頁首


    從 SAX 開始

    SAX (Simple API for XML)是用于處理 XML 的事件驅(qū)動(dòng)方法。它基本由許多回調(diào)函數(shù)組成。例如,每當(dāng) SAX 語法分析器遇到元素的開始標(biāo)記時(shí)就調(diào)用 startElement() 。對(duì)于字符串,將調(diào)用 characters() 回調(diào)函數(shù),然后在元素結(jié)束標(biāo)記處調(diào)用 endElement() 。還有很多回調(diào)函數(shù)用于文檔處理、錯(cuò)誤和其它詞匯結(jié)構(gòu)。現(xiàn)在知道這是怎么回事了。SAX 程序員實(shí)現(xiàn)一個(gè)定義這些回調(diào)函數(shù)的 SAX 接口。SAX 還實(shí)現(xiàn)一個(gè)名為 HandlerBase 的類,該類實(shí)現(xiàn)所有這些回調(diào)函數(shù),并提供所有這些回調(diào)方法的缺省空實(shí)現(xiàn)。(提到這一點(diǎn)是因?yàn)樗诤竺嬷v到的 DOM 中很重要。)SAX 開發(fā)人員只需擴(kuò)展這個(gè)類,然后實(shí)現(xiàn)需要插入特定邏輯的方法。所以,SAX 的關(guān)鍵在于為這些不同的回調(diào)函數(shù)提供代碼,然后允許語法分析器在適當(dāng)?shù)臅r(shí)候觸發(fā)這些回調(diào)函數(shù)中的每一個(gè)。

    因此,典型的 SAX 過程如下:

    • 用特定供應(yīng)商的語法分析器實(shí)現(xiàn)創(chuàng)建一個(gè) SAXParser 實(shí)例
    • 注冊(cè)回調(diào)實(shí)現(xiàn)(例如,通過使用擴(kuò)展 HandlerBase 的類)
    • 開始進(jìn)行語法分析,然后在觸發(fā)回調(diào)實(shí)現(xiàn)時(shí)等待

    JAXP 的 SAX 組件提供執(zhí)行所有這些步驟的簡(jiǎn)單方式。如果沒有 JAXP,SAX 語法分析器要直接從供應(yīng)商類(如 org.apache.xerces.parsers.SAXParser )進(jìn)行實(shí)例化,或者必須使用名為 ParserFactory 的幫助類。第一個(gè)方法的問題很明顯:不獨(dú)立于供應(yīng)商。第二個(gè)方法的問題在于類廠需要一個(gè)自變量,即要使用的語法分析器類的字符串名稱(還是那個(gè) Apache 類 org.apache.xerces.parsers.SAXParser )。可以通過將不同語法分析器作為 String 傳遞來更改語法分析器。使用這種方法不必更改任何 import 語句,但是還是要重新編譯類。這顯然不是最佳解決方案。如果能夠不重新編譯類而更改語法分析器,可能會(huì)簡(jiǎn)單得多,是不是這樣呢?

    JAXP 提供了更好的替代方法:它允許將語法分析器作為 Java 系統(tǒng)屬性來提供。當(dāng)然,當(dāng)從 Sun 下載版本時(shí),將得到使用 Sun 語法分析器的 JAXP 實(shí)現(xiàn)。可以從 Apache XML Web 站點(diǎn)下載在 Apache Xerces 上構(gòu)建其實(shí)現(xiàn)的相同 JAXP 接口。因此(無論哪一種情況),更改正在使用的語法分析器需要更改類路徑設(shè)置,即從一種語法分析器實(shí)現(xiàn)更改到另一個(gè),但是 要求重新編譯代碼。這就是 JAXP 的魔力,或抽象性。

    SAX 語法分析器一瞥

    JAXP SAXParserFactory 類是能夠輕易更改語法分析器實(shí)現(xiàn)的關(guān)鍵所在。必須創(chuàng)建這個(gè)類的新實(shí)例(等一會(huì)將講到)。創(chuàng)建新實(shí)例之后,類廠提供一個(gè)方法來獲得支持 SAX 的語法分析器。在內(nèi)部,JAXP 實(shí)現(xiàn)處理依賴于供應(yīng)商的代碼,使您的代碼不受影響。這個(gè)類廠還提供其它一些優(yōu)秀特性。

    除創(chuàng)建 SAX 語法分析器實(shí)例的基本工作之外,類廠還允許設(shè)置配置選項(xiàng)。這些選項(xiàng)影響所有通過類廠獲得的語法分析器實(shí)例。JAXP 1.0 中兩個(gè)可用的功能是設(shè)置名稱空間敏感性 ( setNamespaceAware (boolean awareness)),和打開確認(rèn) ( setValidating (boolean validating))。請(qǐng)記住,一旦設(shè)置了這些選項(xiàng),在調(diào)用該方法之后,它們將影響 所有從 類廠獲得的實(shí)例。

    設(shè)置了類廠之后,調(diào)用 newSAXParser() 將返回一個(gè)隨時(shí)可用的 JAXP SAXParser 類實(shí)例。這個(gè)類封裝了一個(gè)下層的 SAX 語法分析器(SAX 類 org.xml.sax.Parser 的實(shí)例)。它還防止向語法分析器類添加任何特定于供應(yīng)商的附加功能。(還記得以前對(duì) XmlDocument 的討論嗎?)這個(gè)類可以開始進(jìn)行實(shí)際的語法分析。以下清單顯示如何創(chuàng)建、配置和使用 SAX 類廠。


    清單 1. 使用 SAXParserFactory
    												
    														import java.io.File;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.Writer;
    
    // JAXP
    import javax.xml.parsers.FactoryConfigurationError;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.parsers.SAXParserFactory;
    import javax.xml.parsers.SAXParser;
    
    // SAX
    import org.xml.sax.AttributeList;
    import org.xml.sax.HandlerBase;
    import org.xml.sax.SAXException;
    
    public class TestSAXParsing {
    
     public static void main(String[] args) {
     try {
     if (args.length != 1) {
     System.err.println ("Usage: java TestSAXParsing [filename]");
     System.exit (1);
     }
    
     // 獲得SAX 語法分析器類廠
     SAXParserFactory factory = SAXParserFactory.newInstance();
    
     //設(shè)置設(shè)置名稱空間敏感性選項(xiàng),關(guān)掉確認(rèn)選項(xiàng)
     factory.setValidating(true);
     factory.setNamespaceAware(false);
    
     SAXParser parser = factory.newSAXParser();
     parser.parse(new File(args[0]), new MyHandler());
    
     } catch (ParserConfigurationException e) {
     System.out.println("The underlying parser does not support " +
     " the requested features.");
     } catch (FactoryConfigurationError e) {
     System.out.println("Error occurred obtaining SAX Parser Factory.");
     } catch (Exception e) {
     e.printStackTrace();
     }
     }
    }
    
    class MyHandler extends HandlerBase {
     //通過 DocumentHandler, ErrorHandler等實(shí)現(xiàn)的SAX回調(diào)函數(shù)
    }
    
    												
    										

    請(qǐng)注意,在這段代碼中,在使用類廠時(shí)可能發(fā)生兩個(gè)特定于 JAXP 的問題:無法獲得或配置 SAX 類廠,以及無法配置 SAX 語法分析器。當(dāng)無法獲得 JAXP 實(shí)現(xiàn)中指定的語法分析器或系統(tǒng)屬性時(shí),通常會(huì)發(fā)生第一個(gè)問題 FactoryConfigurationError 。當(dāng)正在使用的語法分析器中的特性不可用時(shí),會(huì)發(fā)生第二個(gè)問題 ParserConfigurationException 。這兩個(gè)問題都容易處理,應(yīng)該不會(huì)對(duì) JAXP 的使用造成任何困難。

    在獲得類廠、關(guān)閉名稱空間并打開“確認(rèn)”之后,將獲得 SAXParser ,然后開始語法分析。請(qǐng)注意, SAX 語法分析器的 parse() 方法取得前面提到的 SAX HandlerBase 類的一個(gè)實(shí)例。(可以通過完整的 Java 清單 查看該類的實(shí)現(xiàn) 。)還要傳遞要進(jìn)行語法分析的文件。但是, SAXParser 所包含的遠(yuǎn)不止這一個(gè)方法。

    使用 SAX 語法分析器

    獲得 SAXParser 類的實(shí)例之后,除了向語法分析器傳遞 File 進(jìn)行語法分析之外,還可以用它做更多的事。由于如今大型應(yīng)用中的應(yīng)用程序組件之間通信方式,“對(duì)象實(shí)例創(chuàng)建者就是其使用者”這樣的假定并不總是安全的。換句話說,一個(gè)組件可能創(chuàng)建 SAXParser 實(shí)例,而另一組件(可能由另一開發(fā)人員編碼)可能需要使用那個(gè)實(shí)例。由于這個(gè)原因,提供了一些方法來確定語法分析器的設(shè)置。執(zhí)行此任務(wù)的兩個(gè)方法是 isValidating() ,它通知調(diào)用程序:語法分析器將要、或不要執(zhí)行“確認(rèn)”,以及 isNamespaceAware() ,它返回一個(gè)指示,說明語法分析器可以或不可以處理 XML 文檔中的名稱空間。雖然這些方法能提供有關(guān)語法分析器可以執(zhí)行功能的信息,但是無法更改這些特性。必須在語法分析器類廠級(jí)別執(zhí)行該操作。

    另外,有多種方法來請(qǐng)求對(duì)文檔進(jìn)行語法分析。除了只接受 File 和 SAX HandlerBase 實(shí)例,SAXParser 的 parse() 方法還能以 String 形式接受 SAX InputSource 、Java InputStream 或 URL,所有這些都要與 HandlerBase 實(shí)例一起提供。所以,不同類型的輸入文檔可以用不同方式的語法分析來處理。

    最后,可以直接通過 SAXParser 的 getParser() 方法獲得和使用下層的 SAX 語法分析器( org.xml.sax.Parser 的實(shí)例)。獲得這個(gè)下層實(shí)例之后,就可以獲得通常的 SAX 方法。下一個(gè)清單顯示 SAXParser 類(這個(gè) JAXP 中 SAX 語法分析的核心類)的各種使用示例。


    清單 2. 使用 JAXP SAXParser
    												
    														 //獲得SAXP的一個(gè)實(shí)例
     SAXParser saxParser = saxFactory.newSAXParser();
    
     //查看是否支持 Validate 選項(xiàng)
     boolean isValidating = saxParser.isValidating();
    
     //查看是否支持 namespace 選項(xiàng)
     boolean isNamespaceAware = saxParser.isNamespaceAware();
    
     // 運(yùn)用一個(gè)File 和一個(gè)SAX HandlerBase 的實(shí)例進(jìn)行多種形式的語法分析
     saxParser.parse(new File(args[0]), myHandlerBaseInstance);
    
     // 運(yùn)用一個(gè) SAX InputSource實(shí)例 和一個(gè) SAX HandlerBase 實(shí)例
     saxParser.parse(mySaxInputSource, myHandlerBaseInstance);
    
     //運(yùn)用一個(gè) InputStream 實(shí)例和一個(gè)SAX HandlerBase 實(shí)例
     saxParser.parse(myInputStream, myHandlerBaseInstance);
    
     // 運(yùn)用一個(gè) URI 和一個(gè)SAX HandlerBase 實(shí)例
     saxParser.parse("http://www.newInstance.com/xml/doc.xml", myHandlerBaseInstance);
    
     //獲得底層的(封裝)SAX 語法分析器 
     org.xml.sax.Parser parser = saxParser.getParser();
    
     //利用底層的語法分析器
     parser.setContentHandler(myContentHandlerInstance);
     parser.setErrorHandler(myErrorHandlerInstance);
     parser.parse(new org.xml.sax.InputSource(args[0]));
    
    												
    										

    目前為止,關(guān)于 SAX 已經(jīng)講了很多,但是還沒有揭示任何不尋常或令人驚奇的東西。事實(shí)上,JAXP 的功能很少,特別是當(dāng) SAX 也牽涉進(jìn)來時(shí)。這很好,因?yàn)橛凶钌俚墓δ苄砸馕吨a可移植性更強(qiáng),并可以由其他開發(fā)人員與任何與 SAX 兼容的 XML 語法分析器一起使用,無論是免費(fèi)(通過開放源碼,希望如此)還是通過商業(yè)途徑。就是這樣。在 JAXP 中使用 SAX 沒有更多的東西。如果已經(jīng)知道 SAX,那么現(xiàn)在已經(jīng)掌握大約 98% 的內(nèi)容。只需學(xué)習(xí)兩個(gè)新類和兩個(gè) Java 異常,您就可以開始了。如果從沒使用過 SAX,那也很簡(jiǎn)單,現(xiàn)在就可以開始。





    回頁首


    處理 DOM

    如果要休息以迎接 DOM 挑戰(zhàn),那么先別休息。在 JAXP 中使用 DOM 的過程與 SAX 幾乎相同,所要做的全部只是更改兩個(gè)類名和一個(gè)返回類型,這樣就差不多了。如果理解 SAX 的工作原理和 DOM 是什么,則不會(huì)有任何問題。

    DOM 和 SAX 的主要差異是它們的 API 結(jié)構(gòu)。SAX 包含一個(gè)基于事件的回調(diào)函數(shù)集,而 DOM 有一個(gè)內(nèi)存中的樹狀結(jié)構(gòu)。換句話說,在 SAX 中,從不需要操作數(shù)據(jù)結(jié)構(gòu)(除非開發(fā)人員手工創(chuàng)建)。因此,SAX 不提供修改 XML 文檔的功能。而 DOM 正好提供這種類型的功能。 org.w3c.dom.Document 類表示 XML 文檔,它由表示元素、屬性和其它 XML 結(jié)構(gòu)的 DOM 節(jié)點(diǎn) 組成。所以,JAXP 無需觸發(fā) SAX 回調(diào),它只負(fù)責(zé)從語法分析返回一個(gè) DOM Document 對(duì)象。

    DOM 語法分析器類廠一瞥

    基本理解 DOM 以及 DOM 和 SAX 的差異之后,就沒什么好說的了。以下代碼看起來與 SAX 代碼類似。首先,獲得 DocumentBuilderFactory (與 SAX 中的方式相同)。然后,配置類廠來處理確認(rèn)和名稱空間(與 SAX 中的方式相同)。下一步,從類廠中檢索 DocumentBuilder (它與 SAXParser 類似)(與 SAX 中的方式相同. . . 啊,您都知道了)。然后,就可以進(jìn)行語法分析了,產(chǎn)生的 DOM Document 對(duì)象傳遞給打印 DOM 樹的方法。


    清單 3. 使用文檔構(gòu)建器類廠
    												
    														import java.io.File;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.Writer;
    
    // JAXP
    import javax.xml.parsers.FactoryConfigurationError;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.DocumentBuilder;
    
    // DOM
    import org.w3c.dom.Document;
    import org.w3c.dom.DocumentType;
    import org.w3c.dom.NamedNodeMap;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    
    public class TestDOMParsing {
    
     public static void main(String[] args) {
     try {
     if (args.length != 1) {
     System.err.println ("Usage: java TestDOMParsing [filename]");
     System.exit (1);
     }
    
     // 獲得 Document Builder Factory
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    
     //打開確認(rèn)選項(xiàng),關(guān)掉名稱空間敏感性選項(xiàng)。
     factory.setValidating(true);
     factory.setNamespaceAware(false);
    
     DocumentBuilder builder = factory.newDocumentBuilder();
     Document doc = builder.parse(new File(args[0]));
    
     // 從DOM 數(shù)中打印文檔,并加一初始空格
     printNode(doc, "");
    
     // 在這里也可以對(duì) DOM 文檔進(jìn)行修改
     } catch (ParserConfigurationException e) {
     System.out.println("The underlying parser does not support the requested features.");
     } catch (FactoryConfigurationError e) {
     System.out.println("Error occurred obtaining Document Builder Factory.");
     } catch (Exception e) {
     e.printStackTrace();
     }
     }
    
     private static void printNode(Node node, String indent) {
     // 打印 DOM 樹
    }
    
    												
    										

    此代碼中可能會(huì)出現(xiàn)兩個(gè)不同的問題(與 JAXP 中的 SAX 類似): FactoryConfigurationErrorParserConfigurationException 。每一個(gè)的原因與 SAX 中的相同。不是實(shí)現(xiàn)類 ( FactoryConfigurationError ) 中有問題,就是語法分析器不支持請(qǐng)求的特性 ( ParserConfigurationException )。DOM 和 SAX 的唯一差異是:在 DOM 中,用 DocumentBuilderFactory 替代 SAXParserFactory ,用 DocumentBuilder 替代 SAXParser 。就這么簡(jiǎn)單!(可以 查看完整代碼清單 ,該清單包括用于打印 DOM 樹的方法。)

    使用 DOM 語法分析器

    有了 DOM 類廠之后,就可以獲得 DocumentBuilder 實(shí)例。 DocumentBuilder 實(shí)例可以使用的方法與 SAX 的非常類似。主要差異是 parse() 的變種不需要 HandlerBase 類的實(shí)例。它們返回表示語法分析之后的 XML 文檔的 DOM Document 實(shí)例。另一唯一不同之處是:為類似于 SAX 的功能提供了兩個(gè)方法:用 SAX ErrorHandler 實(shí)現(xiàn)來處理語法分析時(shí)可能出現(xiàn)的問題的 setErrorHandler() ,和用 SAX EntityResolver 實(shí)現(xiàn)來處理實(shí)體解析的 setEntityResolver() 。如果不熟悉這些概念,則需要通過聯(lián)機(jī)或在我的書中學(xué)習(xí) SAX。以下清單顯示使用這些方法的示例。


    清單 4. 使用 JAXP DocumentBuilder
    												
    														    //獲得一個(gè) DocumentBuilder 實(shí)例
     DocumentBuilder builder = builderFactory.newDocumentBuilder();
    
     //查看是否支持 Validate 選項(xiàng)
     boolean isValidating = builder.isValidating();
    
      //查看是否支持 namespace 選項(xiàng)
     boolean isNamespaceAware = builder.isNamespaceAware();
    
     // 設(shè)置一個(gè) SAX ErrorHandler
     builder.setErrorHandler(myErrorHandlerImpl);
    
     // 設(shè)置一個(gè) SAX EntityResolver
     builder.setEntityResolver(myEntityResolverImpl);
    
     // 運(yùn)用多種方法對(duì) file 進(jìn)行語法分析
     Document doc = builder.parse(new File(args[0]));
    
     // 運(yùn)用 SAX InputSource 
     Document doc = builder.parse(mySaxInputSource);
    
     // 運(yùn)用 InputStream
     Document doc = builder.parse(myInputStream, myHandlerBaseInstance);
    
     // 運(yùn)用 URI
     Document doc = builder.parse("http://www.newInstance.com/xml/doc.xml");
    
    												
    										

    是不是感到 DOM 這一節(jié)有些令人厭煩?有這種想法的不止您一個(gè),寫 DOM 代碼有些令人厭煩是因?yàn)樗侵苯尤〉盟鶎W(xué)的 SAX 知識(shí),然后將其用于 DOM。因此,和朋友、同事打賭吧,說使用 JAXP 只是小菜一碟。





    回頁首


    更改語法分析器

    最后要探討的主題是 JAXP 輕易更改類廠類使用的語法分析器的能力。更改 JAXP 使用的語法分析器實(shí)際意味著更改 類廠,因?yàn)樗?SAXParserDocumentBuilder 實(shí)例都來自這些類廠。既然確定裝入哪個(gè)語法分析器的是類廠,因此,必須更改類廠。可以通過設(shè)置 Java 系統(tǒng)屬性 javax.xml.parsers.SAXParserFactory 來更改要使用的 SAXParserFactory 接口實(shí)現(xiàn)。如果沒有定義該屬性,則返回缺省實(shí)現(xiàn)(供應(yīng)商指定的任何語法分析器)。相同原理適用于 DocumentBuilderFactory 實(shí)現(xiàn)。在這種情況下,將查詢 javax.xml.parsers.DocumentBuilderFactory 系統(tǒng)屬性。就這么簡(jiǎn)單,我們已經(jīng)學(xué)完了!這就是 SAXP 的全部:提供到 SAX 的掛鉤,提供到 DOM 的掛鉤,并允許輕易更改語法分析器。





    回頁首


    結(jié)束語

    如您所見,沒多少?gòu)?fù)雜的東西。更改系統(tǒng)屬性,通過類廠、而不是語法分析器或構(gòu)建器來設(shè)置“確認(rèn)”,以及弄清楚JAXP實(shí)際上不是人們通常所認(rèn)為的那樣,這些是使用 JAXP 的最困難部分。除了沒有 SAX 2.0 和 DOM第二層規(guī)范支持之外,JAXP 在兩個(gè)流行的 Java 和 XML API 之上提供一個(gè)有幫助的可插入層。它使代碼獨(dú)立于供應(yīng)商,并允許不編譯語法分析代碼而更改語法分析器。那么,從 Sun、Apache XML 或其它方便之處下載 JAXP,并使用它吧!繼續(xù)關(guān)注 JAXP 1.1,并增加對(duì) SAX 2 和 DOM 2、XSLT 及更多內(nèi)容的支持。您將在這里獲得第一手新聞,所以,請(qǐng)關(guān)注 developerWorks

    posted on 2006-11-25 17:27 tory 閱讀(301) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 日本无吗免费一二区| 亚洲国产精品无码第一区二区三区 | 亚洲精品无AMM毛片| 亚洲视频精品在线观看| 亚洲一区二区三区在线视频| 插B内射18免费视频| 精品成在人线AV无码免费看 | 国产av无码专区亚洲国产精品| 无码人妻精品一二三区免费| AV无码免费永久在线观看| 另类免费视频一区二区在线观看| 免费无码午夜福利片| 精品女同一区二区三区免费播放| 学生妹亚洲一区二区| 亚洲国产综合在线| 亚洲第一区香蕉_国产a| 亚洲AV无码专区国产乱码电影| 亚洲精品国产高清不卡在线| 国产精品四虎在线观看免费 | 亚洲色欲色欲www在线播放| 亚洲综合色区中文字幕| 亚洲人成电影在线观看青青| 911精品国产亚洲日本美国韩国| 亚洲va在线va天堂va888www| 91麻豆国产自产在线观看亚洲| 亚洲欧洲日产国码高潮αv| 免费A级毛片无码A| 亚洲第一福利网站在线观看| 又粗又大又猛又爽免费视频 | 国产免费人成视频尤勿视频| 2022国内精品免费福利视频 | 亚洲av无码专区国产乱码在线观看| 亚洲色成人WWW永久网站| 亚洲日韩精品射精日| 亚洲精品无码专区在线在线播放| 国产亚洲成归v人片在线观看| 亚洲码国产精品高潮在线| 国产A在亚洲线播放| 91亚洲精品视频| 亚洲一区电影在线观看| 中文字幕在线日亚洲9|