Posted on 2006-03-26 21:44
fortune 閱讀(1302)
評論(1) 編輯 收藏 所屬分類:
java技術(shù)
本文是技巧文章系列的第一篇文章,這些技巧文章將作為在 Java 編程語言中使用 XML 的綜合指南。 我從討論 SAX API 開始。本篇技巧文章回顧了如何獲取 SAX 解析器實(shí)例以及如何對該解析器設(shè)置各種功能和屬性。
在 Java 中使用 XML 是一個內(nèi)容相當(dāng)豐富的主題;可以使用多個 API,而且許多 API 使得使用 XML 簡單得如同從文本文檔讀取行。基于樹的 API(如 DOM)展現(xiàn)了一個內(nèi)存中的 XML 結(jié)構(gòu),該結(jié)構(gòu)對于 GUI 和編輯器來說是最理想的,基于流的 API(如 SAX)對于只需要獲取文檔數(shù)據(jù)的高性能應(yīng)用程序來說很重要。在本技巧文章系列中,我將從基礎(chǔ)知識開始一步步地教您如何在 Java 中使用 XML。同時,您將學(xué)習(xí)許多甚至連眾多專業(yè)人士都不知道的訣竅,所以即使您已經(jīng)具有一些 XML 經(jīng)驗(yàn),也應(yīng)該仔細(xì)閱讀本教程。
我從 SAX(Simple API for XML)開始。雖然該 API 或許是 Java 和 XML API 中最難以掌握的,但它可能也是功能最強(qiáng)的 API。另外,大多數(shù)其它 API 實(shí)現(xiàn)(象 DOM 解析器、JDOM 和 dom4j 等)都部分地基于 SAX 解析器。對于用 XML 和 Java 語言所做的每一件事情,理解 SAX 會給予您一個良好的開端。特別在本篇技巧文章中,我將討論如何獲取 SAX 解析器實(shí)例以及如何對該解析器設(shè)置一些基本功能和屬性。
注:我假設(shè)您已經(jīng)下載了一個符合 SAX 的解析器(如 Apache Xerces-J)(請參閱 參考資料以獲取鏈接)。Apache 站點(diǎn)有大量關(guān)于如何進(jìn)行設(shè)置的信息,但是,基本上您只需要將已下載的 JAR 文件放入 CLASSPATH
中。這些示例假設(shè)您的解析器可用。
獲取解析器
使用 SAX 的第一步實(shí)際上是獲取解析器實(shí)例。在 SAX 中,由 org.xml.sax.XMLReader
類的實(shí)例表示解析器。我在上一篇技巧文章(“Achieving vendor independence with SAX”— 請參閱 參考資料)中對它進(jìn)行了詳細(xì)討論,所以我將不會在這里花大量的時間在上面。清單 1 顯示了在無需編寫與供應(yīng)商相關(guān)的代碼的情況下獲取新 SAX 解析器實(shí)例的正確方法。
清單 1. 獲取 SAX 解析器實(shí)例
// Obtain an instance of an XMLReader implementation from a system property
XMLReader parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
|
通過使用這個方法,您需要將系統(tǒng)屬性 org.xml.sax.driver
設(shè)置成想要裝入的解析器的類名。這是特定于供應(yīng)商的類;對于 Xerces,它應(yīng)該是 org.apache.xerces.parsers.SAXParser
。用 -D
開關(guān)將這個參數(shù)指定給 Java 編譯器:
java -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser some.sample.Class
|
當(dāng)然,您要確保指定的類存在并在類路徑上。
功能
一旦有了解析器實(shí)例,就需要配置它。請注意,這與設(shè)置解析器來處理 XML 中的錯誤、內(nèi)容或結(jié)構(gòu)不同;相反,配置是實(shí)際告訴解析器如何操作的過程。您可以打開驗(yàn)證、關(guān)閉名稱空間檢查及擴(kuò)展實(shí)體。這些行為完全獨(dú)立于特定的 XML 文檔,因此涉及與新解析器實(shí)例的交互。
注:對于那些過于急燥的人來說(我知道您不是這樣的),我當(dāng)然會處理內(nèi)容、錯誤處理及類似的東西。然而,這些主題將在未來的技巧文章中討論,所以您還得復(fù)查。眼下,我們只關(guān)注配置、功能和屬性。
可以用兩種方法配置解析器:功能和屬性。 功能包括打開或關(guān)閉特定功能,比如驗(yàn)證。 屬性包括設(shè)置解析器所使用的特定項(xiàng)的值,如用來驗(yàn)證所有文檔的模式位置。我將先討論功能,然后在下一節(jié)研究屬性。
功能是通過解析器上名為 setFeature()
的方法設(shè)置的,這一點(diǎn)并不奇怪。語法類似于清單 2 所示。
清單 2. 設(shè)置 SAX 解析器的功能
// Obtain an instance of an XMLReader implementation from a system property
XMLReader parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
String featureName = "some feature URI";
boolean featureOn = true;
try {
parser.setFeature(featureName, featureOn);
} catch (SAXNotRecognizedException e) {
System.err.println("Unknown feature specified: " + e.getMessage());
} catch (SAXNotSupportedException e) {
System.err.println("Unsupported feature specified: " + e.getMessage());
} catch (SAXException e) {
System.err.println("Error in setting feature: " + e.getMessage());
}
|
這相當(dāng)清楚,不需要說明;關(guān)鍵是知道可用于 SAX 解析器的常見功能。每個功能均由一個特定的 URI 標(biāo)識。可以從 SAX 網(wǎng)站在線獲得這些 URI 的完整列表(請參閱 參考資料)。一些最常見的功能是驗(yàn)證和名稱空間處理。清單 3 顯示了設(shè)置這兩種屬性的示例。
清單 3. 一些常見功能
// Obtain an instance of an XMLReader implementation from a system property
XMLReader parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
try {
// Turn on validation
parser.setFeature("http://xml.org/sax/features/validation", true);
// Ensure namespace processing is on (the default)
parser.setFeature("http://xml.org/sax/features/namespaces", true);
} catch (SAXNotRecognizedException e) {
System.err.println("Unknown feature specified: " + e.getMessage());
} catch (SAXNotSupportedException e) {
System.err.println("Unsupported feature specified: " + e.getMessage());
} catch (SAXException e) {
System.err.println("Error in setting feature: " + e.getMessage());
}
|
請注意,雖然解析器有幾個標(biāo)準(zhǔn) SAX 功能,但這些解析器可以自由地添加自己的特定于供應(yīng)商的功能。例如,Apache Xerces-J 添加了一些考慮動態(tài)驗(yàn)證以及遇到致命錯誤之后繼續(xù)處理的功能。請參考解析器供應(yīng)商的文檔,以獲取相關(guān)的功能 URI。
屬性
一旦理解了功能,就很容易理解屬性。除了屬性將對象作為參數(shù)而功能獲取布爾值外,它們以完全相同的方式操作。我們使用 setProperty()
方法來設(shè)置屬性,如清單 4 所示。
清單 4. 設(shè)置 SAX 解析器的屬性
// Obtain an instance of an XMLReader implementation from a system property
XMLReader parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
String propertyName = "some property URI";
try {
parser.setProperty(propertyName, obj-arg);
} catch (SAXNotRecognizedException e) {
System.err.println("Unknown property specified: " + e.getMessage());
} catch (SAXNotSupportedException e) {
System.err.println("Unsupported property specified: " + e.getMessage());
} catch (SAXException e) {
System.err.println("Error in setting property: " + e.getMessage());
}
|
這里使用相同的錯誤處理框架,所以您可以容易地在兩種類型的配置選項(xiàng)之間復(fù)制代碼。和功能一樣,SAX 提供了一組標(biāo)準(zhǔn)屬性,供應(yīng)商可以添加他們自己的擴(kuò)展。常見的 SAX 標(biāo)準(zhǔn)的屬性考慮到了設(shè)置詞法處理程序(Lexical Handler)和聲明處理程序(Declaration Handler)(我將在以后的技巧文章中討論這兩個處理程序)。像 Apache Xerces 之類的解析器對它們進(jìn)行了擴(kuò)展,例如,使它們能夠設(shè)置輸入緩沖區(qū)大小以及要在驗(yàn)證中使用的外部模式的位置。清單 5 顯示了幾個實(shí)際使用中的屬性。
清單 5. 一些常見屬性
// Obtain an instance of an XMLReader implementation from a system property
XMLReader parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
try {
// Set the chunk to read in by SAX
parser.setProperty("http://apache.org/xml/properties/input-buffer-size",
new Integer(2048));
// Set a LexicalHandler
parser.setProperty("http://xml.org/sax/properties/lexical-handler",
new MyLexicalHandler());
} catch (SAXNotRecognizedException e) {
System.err.println("Unknown feature specified: " + e.getMessage());
} catch (SAXNotSupportedException e) {
System.err.println("Unsupported feature specified: " + e.getMessage());
} catch (SAXException e) {
System.err.println("Error in setting feature: " + e.getMessage());
}
|