目的
- XMLを解析する際に、リモートDTDを読ませない「おまじない」をすることが多い
- おまじないじゃなく、ちゃんと理解しておいたほうが良いよね
- でも、詳しいことは自分でも調べてね
- 動作確認は Java 8u65 で行いました
よくある実装例
Java で XML を解析する際、リモートDTDなどを読み込まないように、以下のような設定をすることがあると思います。
※もちろん、読み込ませなくて大丈夫な場合だけ。
	public static Document readXML(File file)
			throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		// リモートDTDなどを一切読み込まない
		factory.setNamespaceAware(false);
		factory.setValidating(false);
		factory.setFeature("http://xml.org/sax/features/namespaces", false);
		factory.setFeature("http://xml.org/sax/features/validation", false);
		factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
		factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(file);
		return document;
	}
それぞれの意味を調べてみました。
整理
Feature "http://xml.org/sax/features/namespaces"
XML名前空間を処理する(true)/しない(false)を指定します。
内容的には DocumentBuilderFactory#setNamespaceAware() と同じもののようです。
上記 Xerces のサイトではデフォルトは true と表記されていますが、Javadoc でも実際に動かしてみてもデフォルト値は false のようです。
Feature "http://xml.org/sax/features/validation"
構文解析時にドキュメントの妥当性を検証する(true)/しない(false)を指定します。
内容的には DocumentBuilderFactory#setValidating() と同じもののようです。
上記 Xerces のサイトでも、Javadoc でも、実際に動かした結果も、デフォルト値は false のようです。
Feature "http://apache.org/xml/features/nonvalidating/load-dtd-grammar"
解析する際に DTD に定義されているデフォルトの属性と属性セットの種類を追加する(true)/しない(false)を指定します。
上記 Xerces のサイトではデフォルトは true と表記されていますが、実際に動かしてみるとデフォルト値は false のようです。
Feature "http://apache.org/xml/features/nonvalidating/load-external-dtd"
外部DTDをロードする(true)/しない(false)を指定します。
上記 Xerces のサイトでも、実際に動かした結果もデフォルト値は true のようです。
まとめ
| Feature | Xerces | Java 8u65 | 
|---|---|---|
| "http://xml.org/sax/features/namespaces" | true | false | 
| "http://xml.org/sax/features/validation" | false | false | 
| "http://apache.org/xml/features/nonvalidating/load-dtd-grammar" | true | false | 
| "http://apache.org/xml/features/nonvalidating/load-external-dtd" | true | true | 
- 必要なのは setFeature で "http://apache.org/xml/features/nonvalidating/load-external-dtd" を false にしておくことだけみたい
- 4つともやっておいたほうが安心できるなら、念のためしておいてもいいかもね(特に Xerces では true になっている項目は)
- setValidating(), setNamespaceAware() と、対応する Feature の両方を設定するのは意味がなさそう