轉自:http://www.ibm.com/developerworks/cn/xml/tips/x-tipsaxis/index.html
當您使用 SAX API 時,所有輸入都從使用 org.xml.sax.InputSource 類開始。這個類包含在 SAX API 中,並且提供了輸入規範(通過類似於檔案或 I/O 流的標準 Java 構造),同時還提供一個公用的系統標識。 接著,SAX 在解析時從 InputSource 抽取這些資訊,從而能夠解析外部實體以及其它特定於文檔來源的資源。
類似地,當您對 SAX 使用封裝器(類似於 JAXP API)時,可以調用不同方法。最後,解析使用 SAX InputSource 。例如,考慮 清單 1 中所示的程式碼片段,它使用 JAXP 來啟動 SAX 解析。
清單 1. 將 JAXP 用於 SAX 解析
SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser parser = spf.newSAXParser(); parser.parse(myFile, myHandler);
即使輸入了 java.io.File 檔案,它也會在被轉交給底層 SAX 實現之前轉換成 SAX InputSource 。之所以發生這個轉換,是因為這個 JAXP 代碼最終訪問 org.xml.sax.XMLReader 類,該類只為啟動解析提供 清單 2 中所示的兩個特徵符。
清單 2. 用於 XMLReader 的解析進入點
public void parse(InputSource inputSource); public void parse(String systemID);
在此基礎上,大多數 SAX 解析器實現(如 Apache Xerces)實際上將字串系統標識轉換為 InputSource ,並將它分配給接收 InputSource 的 parse() 版本。無論您如何編碼自己的應用程式,SAX 最終都接收 InputSource 來用於解析。但是,並非所有這樣處理的方法都同等地好。
為了避免您代碼中出現令人不快的意外,最好直接使用 SAX InputSource 類,而不是讓 JAXP 或 SAX 為您處理這個任務。因為實現必須要處理每種可能的情況,所以您常常會看到構造 InputSource 執行個體的代碼,類似於 清單 3 中所示。
清單 3. 一般的 InputSource 構造方法
InputSource inputSource = new InputSource(); // May be a null parameter inputSource.setByteStream(inputStream); // May be a null parameter inputSource.setCharacterStream(reader); // May be a null parameter inputSource.setSystemId(systemId); // May be a null parameter inputSource.setPublicId(publicId); // Derived parameter inputSource.setEncoding(encoding);
正如您從注釋中看到的,這些方法中的許多被傳遞了 null 參數。雖然執行這些方法不會花費很多時間,但 XML 解析應用程式中的每一秒都很關鍵;遺憾的是,這些不執行任何操作的方法浪費了寶貴的時間。通過自行構造 InputSource 執行個體,您可以將這個過程簡化為一至兩個方法調用,如 清單 4 所示。
清單 4. 改進 InputSource 構造
InputSource inputSource = new InputSource(myInputStream); inputSource.setSystemId("http://www.oreilly.com"); inputSource.setEncoding("UTF-8");
我還使用了 setEncoding() 方法來通知 SAX 解析器使用何種編碼;在涉及國際化或使用多位元組字元集的 XML 應用程式中,這一點很重要。
但是,這裡產生了另一個問題:對於字元編碼,用手工設定字元編碼的編碼與所提供的輸入資料流(通過 java.io.InputStream 或 java.io.Reader )所用的編碼 不同 ,這種情況很常見。如果這些編碼不匹配,就可能發生各種解析問題。要避免這種情況,請始終用 Java InputStream 建立您的 InputSource ,而不要用 Reader 或 String 系統標識(這些都是 JAXP API 的可能選項)。當您提供 InputStream 時,SAX 實現將流封裝在 InputStreamReader 中;然後 SAX 自動從流中檢測正確的字元編碼。隨後,您可以省略 setEncoding() 步驟,再次減少方法調用。結果是應用程式運行更快了,並且字元編碼始終正確。