あるXML文書をパースするとエラーになる原因は?
あるXML文書をパースしようとすると「External entity not found」エラーが発生します。外部DTDを見ないようにすればいいと思うのですが、そういうことはできますか?

回答/富士ソフトABC株式会社 技術センター
2001/6/28

 まずは、もう一度質問を詳しく紹介します。

@ITの記事の「DOMプログラムの実例」を参考に、DOM(JAXP)を使って、設定ファイルのweb.xml を解析しようとしています。ですが、いざ web.xml をパースしようとすると、「External entity not found」とエラーになってしまいます。

web.xmlのDOCTYPEは以下のようになっており、パース時に外部DTDである「web-app_2.2.dtd」を見にいってしまうようです。

<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN' 'http://java.sun.com/j2ee/dtds/web-app_2.2.dtd'>

妥当性検査をしないように factory.setValidating(false); を指定しても結果は同じでした。このような外部DTDを見に行かないようにはできないでしょうか?

 筆者が試した範囲では、web.xmlのパースは正常に動作しました。テストには、最小のweb.xml を使用しています。下記に環境を示しておきます。

  • Microsoft Windows 2000 Professional (SP1)
  • JDK1.3.0_02
  • JAXP-1.1

 エラーになった原因が、JDKのバージョンの違いの問題なのかどうなのか不明ですが、表記のエラー「External entity not found」について考えられる点を以下に説明しましょう。

 まず、質問内容に「妥当性検査をしないように factory.setValidating(false); を指定しても同じでした。このような外部DTDを見にいかないようにはできないでしょうか?」とありますが、W3C勧告から判断すると「できません」となります。

 例えば、以下のような実体参照があるXML文書を考えてみましょう。

<?xml version="1.0" ?>
<web-app>&test;</web-app>
実体宣言が行われていない実体参照を使ったXML文書の例

 整形式のXML文書に対する検証でも、実体宣言がされているか、再帰的に使用していないかなどが検証されます。上記のXML文書では実体宣言が行われていないので、整形式の検証でもエラーとして判断されます。これは一例ですが、外部実体(外部DTDサブセット)が宣言されていれば、整形式の検証を行うためにもそれを読み込む必要があるのです。

 またsetValidatingの動作も簡単に説明します。以下の XML文書とDTDを見てください(確認のためにXML文書をパースするだけのプログラムSample.javaを作りましたので参考にしてください)。

-----test2.xml-----
<?xml version="1.0" ?>
<!DOCTYPE test SYSTEM "test.dtd">
<test>&test;</test>

-----test.dtd-----
<!ELEMENT test (#PCDATA)>
<!ENTITY test "&lt;">
実体宣言が行われていない実体参照を使ったXML文書の例(test2.xmltest.dtdtest.java

 この XML文書をパースすると、整形式の検証は問題なく終了することが分かります。しかし、setValidating(true)として、妥当性の検証を行った場合には、実際に置き換えが行われますので、エラーとなります。このようにきちんと整形式か妥当なXML文書かの判断が行われていることが分かります。

 それでは、質問にあるようなXML文書を処理する場合に考えられる問題点および解決策を以下に示します。

  1. ネットワーク接続環境がない場合
  2. Javaの起動オプションが誤っている場合
  3. 外部DTDサブセットが存在しなくとも処理を継続するXMLプロセッサを使う方法

 まず、ネットワークの接続環境がない場合ですが、妥当性の検証が必要でなければ、文書型定義を削除するかコメントにして実行してください。web.xmlにあったweb-app_2_2.dtdには、実体参照がありませんので問題なく検証できるはずです。

 妥当性の検証が必要であれば、別途web-app_2_2.dtdを入手して、ローカルに置いたうえで文書型定義を変更してください。

 次に考えられる原因として、プロキシを使用しているネットワーク環境の場合で、javaの起動オプションが誤っていることが考えられます。ただし、この場合には

java.net.UnknownHostException

とエラー表示されますので、質問の内容とは現象が異なるようです。プロキシを使用する場合には、javaの起動オプションでシステムプロパティを指定する必要があります。以下に例を示します。

java -DproxySet=true -DproxyHost=proxyhost [-DproxyPort=portNumber] ProgramName

 最後に、外部DTDサブセットが存在しなくとも処理を継続するXMLプロセッサを使う方法があります。

 ADOS社のXMLパーサであるAlpha XMLは、外部のDTDファイルが存在しなくとも処理を中断せずに検証を続けて行います。しかし、Alpha XMLはJAXPに対応していないため、org.w3c.dom以外の操作は特殊ですので使用する場合には注意が必要です。

「Ask XML Expert」

 



XML & SOA フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日月間