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」の場合、W3CDTD にアクセスできないことが
分かっている。

  1. MSIE」が含まれている
  2. Java/<数字>」で始まる

例えば、「Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)」や
Java/1.5.0_12」だと、上記条件にマッチして W3CDTD にアクセスできない。


回避策としては「User-Agent」を上記条件にマッチしないように設定すればいいわけで、
プログラムの修正が可能であれば、 URLConnection クラスの setRequestProperty()
メソッドで任意の「User-Agent」をセットすればいいのだが、今回はプログラムの
修正はしたくないのでシステムプロパティ「http.agent」に任意の文字列をセット
するようすればいい。


そうすれば、例えば Java 1.5.0_12 だと「User-Agent」は以下のようになる。

<任意の文字列> Java 1.5.0_12

懸念事項としては、W3C で制限している条件が「Java/<数字> で始まる」ではなく、
Java を含む」などにした場合、上記対応では回避できなくなるということだ。


まあ、全うなやり方はやっぱりEntityResolverかな。