DTD 503 Error
この間、Xerces を使った XML ドキュメントのパース時に以下のエラーが発生した。
Caused by: java.io.IOException: Server returned HTTP response code:
503 for URL: http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
どうやら W3C のサイトにある DTD に頻繁にアクセスが発生し負担になったため
制限しているらしい。(W3C Systeam's blog - W3C's Excessive DTD Traffic)
Xerces を使って XML ドキュメントをパースする際には、以下の方法で DTD の
バリデーションをオフにすることもできるが、
setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
これだと DTD に定義されている実体参照を参照している場合に、
参照先の文字列に展開されないなどの問題が発生する。
EntityResolverを使えば、ローカルの DTD にアクセスするように変更することも
できそうだが、プログラムの修正が必要になる。
プログラムの修正をせずになんとか DTD にアクセスできないか調査したところ、
HTTP の「User-Agent」で制限していることが分かった。現在のところ以下の
条件にマッチした「User-Agent」の場合、W3C の DTD にアクセスできないことが
分かっている。
例えば、「Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)」や
「Java/1.5.0_12」だと、上記条件にマッチして W3C の DTD にアクセスできない。
回避策としては「User-Agent」を上記条件にマッチしないように設定すればいいわけで、
プログラムの修正が可能であれば、 URLConnection クラスの setRequestProperty()
メソッドで任意の「User-Agent」をセットすればいいのだが、今回はプログラムの
修正はしたくないのでシステムプロパティ「http.agent」に任意の文字列をセット
するようすればいい。
そうすれば、例えば Java 1.5.0_12 だと「User-Agent」は以下のようになる。
<任意の文字列> Java 1.5.0_12
懸念事項としては、W3C で制限している条件が「Java/<数字> で始まる」ではなく、
「Java を含む」などにした場合、上記対応では回避できなくなるということだ。
まあ、全うなやり方はやっぱりEntityResolverかな。