web-dev-qa-db-ja.com

SAXパーサーにXML宣言からエンコーディングを決定させる方法は?

さまざまなソースからのxmlファイルを解析しようとしています(これについてはほとんど制御できません)。それらのほとんどはUTF-8でエンコードされており、次のスニペットを使用しても問題は発生しません。

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
FeedHandler handler = new FeedHandler();
InputSource is = new InputSource(getInputStream());
parser.parse(is, handler);

SAXのデフォルトはUTF-8なので、これで問題ありません。ただし、一部のドキュメントでは次のように宣言しています。

<?xml version="1.0" encoding="ISO-8859-1"?>

ISO-8859-1が宣言されていても、SAXはデフォルトでUTF-8になります。追加した場合のみ:

is.setEncoding("ISO-8859-1");

SAXは正しいエンコーディングを使用しますか?.

特に設定せずに、SAXにxml宣言から正しいエンコーディングを自動的に検出させるにはどうすればよいですか?これが必要なのは、ファイルのエンコーディングがどのようなものになるか、事前にわからないためです。

前もってありがとう、アラン

26
Allan

InputSource の引数としてInputStreamを使用しますSaxがエンコードを自動検出するようにします。

特定のエンコーディングを設定したい場合は、Readerを指定したエンコーディングまたは setEncoding メソッドで使用します。

どうして? 自動検出エンコーディングアルゴリズム は、文字に変換されずに生データを必要とするためです。

件名の質問は次のとおりです:SAXパーサーにxml宣言からのエンコードを決定させる方法誤解を招く質問に対するAllanの回答を見つけ、提供しましたJörnHorstmannのコメントと私の後の経験に基づく代替案。

14
Jarekczek

自分で答えを見つけました。

SAXパーサーは、内部およびInputSourceドキュメントからのInputSourceを使用します。

SAXパーサーは、InputSourceオブジェクトを使用して、XML入力の読み取り方法を決定します。使用可能な文字ストリームがある場合、パーサーはそのストリームで見つかったテキストエンコーディング宣言を無視して、そのストリームを直接読み取ります。文字ストリームはないがバイトストリームがある場合、パーサーはInputSourceで指定されたエンコーディングを使用してそのバイトストリームを使用するか、それ以外の場合(エンコーディングが指定されていない場合)のようなアルゴリズムを使用して文字エンコーディングを自動検出します。 XML仕様。文字ストリームもバイトストリームも使用できない場合、パーサーはシステム識別子で識別されるリソースへのURI接続を開こうとします。

したがって、基本的には、文字ストリームをパーサーに渡して、正しいエンコーディングを取得する必要があります。以下の解決策を参照してください:

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
FeedHandler handler = new FeedHandler();
Reader isr = new InputStreamReader(getInputStream());
InputSource is = new InputSource();
is.setCharacterStream(isr);
parser.parse(is, handler);
9
Allan