このメソッドでxmlファイル(変数f)を解析すると、エラーが発生します
C:\ Documents and Settings\joe\Desktop\aicpcudev\OnlineModule\map.dtd(システムは指定されたパスを見つけることができません)
私はdtdを持っていないし、必要もないことを知っています。 DTD参照エラーを無視しながら、このFileオブジェクトをDocumentオブジェクトに解析するにはどうすればよいですか?
private static Document getDoc(File f, String docId) throws Exception{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(f);
return doc;
}
@ anjanb によって提案されたアプローチと同様のアプローチ
builder.setEntityResolver(new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
if (systemId.contains("foo.dtd")) {
return new InputSource(new StringReader(""));
} else {
return null;
}
}
});
空のInputSourceを返すだけでも同様に機能することがわかりました。
DocumentBuilderFactoryで機能を設定してみてください。
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(true);
dbf.setFeature("http://xml.org/sax/features/namespaces", false);
dbf.setFeature("http://xml.org/sax/features/validation", false);
dbf.setFeature("http://Apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
dbf.setFeature("http://Apache.org/xml/features/nonvalidating/load-external-dtd", false);
DocumentBuilder db = dbf.newDocumentBuilder();
...
最終的に、オプションはパーサーの実装に固有のものだと思います。 ここにXerces2のドキュメントがあります それが役立つ場合。
DTDファイルがXMLとともにjarファイルにあるという問題を発見しました。次のように、ここの例に基づいて問題を解決しました。-
DocumentBuilder db = dbf.newDocumentBuilder();
db.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
if (systemId.contains("doc.dtd")) {
InputStream dtdStream = MyClass.class
.getResourceAsStream("/my/package/doc.dtd");
return new InputSource(dtdStream);
} else {
return null;
}
}
});
ソースXML(DTDを使用)
<!DOCTYPE MYSERVICE SYSTEM "./MYSERVICE.DTD">
<MYACCSERVICE>
<REQ_PAYLOAD>
<ACCOUNT>1234567890</ACCOUNT>
<BRANCH>001</BRANCH>
<CURRENCY>USD</CURRENCY>
<TRANS_REFERENCE>201611100000777</TRANS_REFERENCE>
</REQ_PAYLOAD>
</MYACCSERVICE>
上記のXMLを文字列として受け入れ、DTD宣言を削除するためのJava DOM実装
public Document removeDTDFromXML(String payload) throws Exception {
System.out.println("### Payload received in XMlDTDRemover: " + payload);
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
dbf.setValidating(false);
dbf.setNamespaceAware(true);
dbf.setFeature("http://xml.org/sax/features/namespaces", false);
dbf.setFeature("http://xml.org/sax/features/validation", false);
dbf.setFeature("http://Apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
dbf.setFeature("http://Apache.org/xml/features/nonvalidating/load-external-dtd", false);
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(payload));
doc = db.parse(is);
} catch (ParserConfigurationException e) {
System.out.println("Parse Error: " + e.getMessage());
return null;
} catch (SAXException e) {
System.out.println("SAX Error: " + e.getMessage());
return null;
} catch (IOException e) {
System.out.println("IO Error: " + e.getMessage());
return null;
}
return doc;
}
宛先XML(DTDなし)
<MYACCSERVICE>
<REQ_PAYLOAD>
<ACCOUNT>1234567890</ACCOUNT>
<BRANCH>001</BRANCH>
<CURRENCY>USD</CURRENCY>
<TRANS_REFERENCE>201611100000777</TRANS_REFERENCE>
</REQ_PAYLOAD>
</MYACCSERVICE>
同じ問題が発生した別のユーザーは次のとおりです。 http://forums.Sun.com/thread.jspa?threadID=284209&forumID=34
その投稿のユーザーddssotは言う
myDocumentBuilder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(Java.lang.String publicId, Java.lang.String systemId)
throws SAXException, Java.io.IOException
{
if (publicId.equals("--myDTDpublicID--"))
// this deactivates the Open Office DTD
return new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes()));
else return null;
}
});
ユーザーはさらに、「ご覧のとおり、パーサーがDTDにヒットすると、エンティティリゾルバーが呼び出されます。特定のIDでDTDを認識し、実際のDTDではなく空のXMLドキュメントを返し、すべての検証を停止します...」
お役に立てれば。
私はdtdを持っていないし、必要もないことを知っています。
私はこの声明を疑っています。ドキュメントにはエンティティ参照が含まれていますか?もしそうなら、あなたは間違いなくDTDが必要です。
とにかく、これを防ぐ通常の方法は、XMLカタログを使用して「map.dtd」のローカルパスを定義することです。