6.3 SAXパーサに関する注意事項

SAXパーサに関する注意事項を次の表に示します。

表6-7 SAXパーサに関する注意事項

項番注意事項
1マルチスレッドプログラミングをする場合,SAXParserFactoryクラスはスレッドセーフではありません。したがって,複数のスレッドが同時に同一のSAXParserFactoryインスタンスにアクセスしてはいけません。スレッド間の競合を避けるため,次のどちらかの方法を使用してください。
  • 各スレッドに1つのSAXParserFactoryインスタンスを持つ。
  • 各スレッドが排他的にSAXParserFactoryインスタンスにアクセスする。
2マルチスレッドプログラミングをする場合,SAXParserクラスはスレッドセーフではありません。したがって,複数のスレッドが同時に同一のSAXParserインスタンスを使用してはいけません。スレッド間の競合を避けるため,次の方法を使用してください。
  • 各スレッドに1つのSAXParserインスタンスを持つ。
3マルチスレッドプログラミングをする場合,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpersパッケージで規定されたオブジェクトはスレッドセーフではありません。したがって,複数のスレッドが同時にこれらのオブジェクトにアクセスしてはいけません。更新系メソッドだけではなく,参照系メソッドでも同時にアクセスしてはいけません。スレッド間の競合を避けるため,次の方法を使用してください。
  • 各スレッドが排他的にこれらのオブジェクトにアクセスする。
4SAXパーサは,1つの文字列データを複数の文字列(チャンク)に分割し,複数のcharactersイベントとしてアプリケーションに報告することが許されています。したがって,ContentHandlerの実装では,文字列データが分割されることを意識する必要があります。
ContentHandlerの実装例を次に示します。この例では,charactersイベントが発生するたびに文字列データをバッファリングしていき,endElementイベントが報告された時点で文字列データの終端と見なしています。

class MyHandler implements ContentHandler {
String str = null;
StringBuffer buffer = null;
:
public void startElement(String uri, String localName, String qName, Attributes atts)
throws SAXException {
buffer = new StringBuffer();
}
:
public void characters(char c[], int start, int length) throws SAXException {
buffer.append(c, start, length);
}
:

public void endElement(String uri, String name, String qname) throws SAXException {
str = buffer.toString();
}
:

5XMLReaderFactory クラスのcreateXMLReader(String className)メソッドを使用し,XMLReader の生成を行う場合は,引数classNameに"com.cosminexus.jaxp.impl.parsers.parsers.SAXParser"を指定してください。XMLReader の生成例を次に示します。

XMLReader reader =
XMLReaderFactory.createXMLReader("com.cosminexus.jaxp.impl.parsers.parsers.SAXParser");

6SAXParserクラスの「InputStreamやInputSourceを引数とするparseメソッド」でエラーが発生したとき,エラーハンドラへ渡されるSAXParseExceptionにgetSystemIdメソッドを適用するとnullが返される場合があります。エラー発生元のシステム識別子を返すようにする場合は,parseメソッドを次のように使用してください。
  • parse(InputStream is, …, String systemId)メソッドで,システム識別子を引数systemIdに指定する。
  • parse(InputSource is, …)メソッドで,システム識別子を設定したInputSourceを引数isに指定する。
7BOM(Byte Order Mark)付きのUTF-16で保存されたXML文書をparse(InputSource is, …)メソッドで解析する場合,InputSourceにsetEncodingメソッドを適用するときは引数に"UTF-16"を指定してください。
8内部エンティティを定義する文字列中に,477文字以上の要素名が含まれていると,java.lang.IndexOutOfBoundsException例外が発生する場合があります。
9次の両方の条件に該当する場合,java.lang.IllegalStateException例外が発生することがあります。
  1. ValidatorHandler.getTypeInfoProviderメソッドでTypeInfoProviderオブジェクトを取得する。
  2. SAXのendElementイベントのイベントハンドラで,1.で示すオブジェクトに対してgetElementTypeInfoメソッドを呼び出す。