老讀者都知道 Brett McLaughlin 對(duì) SAX 情有獨(dú)鐘,對(duì) DOM 則漠不關(guān)心。他尤其反感 Sun 公司對(duì)于 API 的做法,從之前將 API 封裝在 JAXP(早期版本)之類的包中到近來在最新版的 Java™ 技術(shù)和 J2SE(Java 2 Platform, Standard Edition 1.2-1.4 )中幾乎完全取代了這些 API。
對(duì)于剛接觸 Java 和 XML 的程序員(或者通過 Sun 和 J2SE 才接觸到 XML 的程序員)來說,都有必要簡要回顧一下早期的 JAXP。那時(shí),JAXP 是 Java 和 XML 領(lǐng)域中排行第三的 API,風(fēng)靡程度僅次于 SAX(Simple API for XML)和 DOM(Document Object Model)。JAXP 的目標(biāo)非常簡單:使 SAX 和 DOM 的使用更加簡單,尤其是在供應(yīng)商中立領(lǐng)域。
最初,JAXP 的目的僅僅是向 SAX 和 DOM 提供便利性和供應(yīng)商中立性。根據(jù)這一點(diǎn),JAXP 從未想過要替代 SAX 或 DOM;事實(shí)上,JAXP 在其早期版本中擁有一些方法,getXMLReader()
和 getDOMParser()
就是其中的兩個(gè)。 顯而易見,這些方法的存在表明 JAXP 的作者希望 開發(fā)人員使用 JAXP,然后操作底層的 SAX 和 DOM 實(shí)現(xiàn)類。
還有一點(diǎn)值得注意,雖然 JAXP 在這些年中不斷地加入大量的功能,但是這兩個(gè)方法從未修改過。有的人會(huì)說這不過是出于向后兼容性的考慮,不過這確實(shí)反應(yīng)了 JAXP 從未打算將 SAX 或 DOM 取而代之。JAXP 只不過是將它們封裝起來,這樣開發(fā)人員就不必使用大量特定于供應(yīng)商的代碼來調(diào)用 SAX 或 DOM了。
在早期的 Java 和 XML 編程中,存在大量 的 XML 解析器(最初的 Xerces 和 XML4J,Sun 公司的 Crimson,Oracle 公司的 XML 解析器,以及一些如今人們從未聽過的解析器。)當(dāng)我們編寫一個(gè)與 XML 協(xié)作和交互的應(yīng)用程序時(shí),需要將 SAX 和 DOM API 連接到這些解析器實(shí)現(xiàn),通常所使用的方法是將解析器類名告知 SAX 或 DOM,有點(diǎn)類似如下的方式:
Parser parser = new org.apache.xercers.parsers.SAXParser(); |
注意:我有意使用了較舊的 SAX Parser
接口;它是舊的 SAX 1 解析類,在 JAXP 成為問題的時(shí)期所有人都在使用它。
JAXP 引入了一個(gè) javax.xml.parsers.SAXParserFactory
系統(tǒng)屬性,它允許我們指定解析器工廠實(shí)現(xiàn)(工廠中提供了想要使用的解析器)。可以通過一個(gè) System.setProperty()
系統(tǒng)屬性指定工廠,也可以通過某些位置下的 jaxp.properties 文件來指定(本質(zhì)上說,即應(yīng)用程序類路徑中的任何位置)。
無論采用何種方式指定這一屬性 — 或者其對(duì)應(yīng)的 DOM 屬性 javax.xml.parsers.DocumentBuilderFactory
— 都需要避免在解析代碼中出現(xiàn)任何類名。這也是 JAXP 存在的首要原因:防止將此類信息直接放入代碼。可以通過改變屬性值來方便地修改各種屬性,或者甚至建立多個(gè) jaxp.properties 文件用于不同的解析器實(shí)現(xiàn),并且在需要時(shí)對(duì)它們進(jìn)行切換。