Сделать DocumentBuilder.разбор игнорировать ссылки DTD
когда я разбираю свой xml-файл (переменная f) в этом методе, я получаю ошибку
C:Documents и настройкиjoeDesktopaicpcudevOnlineModulemap.dtd (система не может найти указанный путь)
Я знаю, что у меня нет dtd, и мне это не нужно. Как я могу разобрать этот объект файла в объект документа, игнорируя ошибки ссылки DTD?
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;
}
6 ответов:
аналогичный подход к тому, который предлагает @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 был в файле jar вместе с XML. Я решил эту проблему на основе приведенных здесь примеров следующим образом: -
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; } } });
Я знаю, что у меня нет dtd, и мне это не нужно.
Я с подозрением отношусь к этому утверждению; содержит ли ваш документ какие-либо ссылки на сущности? Если это так, вам определенно нужен DTD.
в любом случае, обычный способ предотвратить это-использовать каталог XML для определения локального пути для "map.шаблон DTD."
вот еще один пользователь, который получил ту же проблему: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, вызывается распознаватель сущностей. Я узнаю свой DTD с его конкретным идентификатором и возвращаю пустой XML-документ вместо реального DTD, останавливая всю проверку..."
надеюсь, что это помогает.
исходный 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>
реализация Java DOM для принятия выше XML в качестве строки и удаления объявления DTD
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>