XMLをパースするんじゃなくて、単に読み込む。
XMLをパースするのではなくて、Unicode文字列として読み込む必要が生じて、ハタと困った。そんなAPI無いし。面倒なのは、エンコーディングを判定する部分で、自分で、<?xml ... encoding="xxx"?>をパースするっていうのも、芸が無い。で、staxのAPIを見ていたら、START_DOCUMENTのイベントを拾ってやれば、XMLStreamReader.getEncoding()で取れそう。最初に、簡単なstaxの動作確認プログラムを作成。
public static void main(String[] args) throws Exception {
XMLStreamReader reader = XMLInputFactory.newInstance()
.createXMLStreamReader(new BufferedInputStream(new FileInputStream(args[0])));
try {
while (reader.hasNext()) {
System.err.println("Event: " + reader.next());
}
}
finally {
reader.close();
}
}
こんなファイルで動作を確認すると、
<?xml version="1.0" encoding="Shift_JIS"?>
<hello/>
Event: 1
Event: 2
Event: 8
API仕様書を見ると、START_DOCUMENTは、イベント番号7なんだけど、出力されていない。変だなぁと思って、Googleさんに聞いてみると、あぁ、あった。このサイトに、when XMLStreamReader is created, it is positioned at START_DOCUMENT event.とある。つまり、next()を呼ぶ前が、START_DOCUMENTが出た状態なのね。というわけで、修正
public static void main(String[] args) throws Exception {
XMLStreamReader reader = XMLInputFactory.newInstance()
.createXMLStreamReader(new BufferedInputStream(new FileInputStream(args[0])));
try {
while (true) {
System.err.println("Event: " + reader.getEventType());
if (reader.hasNext()) reader.next();
else break;
}
}
finally {
reader.close();
}
}
今度は、ちゃんとSTART_DOCUMENTも出力された。
Event: 7
Event: 1
Event: 2
Event: 8
しかし、なんともしっくり行かない。Iteratorとソックリのメソッド名でありながら、動きが微妙に違うってのは、良くない設計だ。しょっぱなが、START_DOCUMENTなんで、エンコーディングは、
public static void main(String[] args) throws Exception {
InputStream is = new BufferedInputStream(new FileInputStream(args[0]));
XMLStreamReader reader = null;
try {
reader = XMLInputFactory.newInstance().createXMLStreamReader(is);
System.err.println("Encoding: " + reader.getEncoding());
}
finally {
is.close();
}
}
で取れる。ただ、API仕様書によると、getEncoding()はnullを返すかもしれないそうなんで注意。もっとも、プリアンブル外してみたりしたけど、Sunのjaxp 1.4.2では、getEncoding()がnullを返すことは無かった。





