Kiedy analizuję mój plik xml (zmienna f) w tej metodzie, pojawia się błąd
C: \ Documents and Settings \ joe \ Desktop \ aicpcudev \ OnlineModule \ map.dtd (system nie może znaleźć określonej ścieżki)
Wiem, że nie mam dtd i nie potrzebuję go. Jak mogę przeanalizować ten obiekt File w obiekt Document, ignorując błędy odniesienia 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;
}
Odpowiedzi:
Podejście podobne do sugerowanego przez @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; } } });
Okazało się, że po prostu zwrócenie pustego źródła danych wejściowych działa równie dobrze?
źródło
Spróbuj ustawić funkcje w 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(); ...
Ostatecznie myślę, że opcje są specyficzne dla implementacji parsera. Tutaj jest trochę dokumentacji dla Xerces2, jeśli to pomoże.
źródło
load-external-dtd
) załatwił mi sprawę - dzięki.dbf.setNamespaceAware(true);
load-external-dtd
ustawienie było wystarczające.Znalazłem problem polegający na tym, że plik DTD znajdował się w pliku jar wraz z plikiem XML. Rozwiązałem problem na podstawie poniższych przykładów w następujący sposób: -
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; } } });
źródło
Źródłowy XML (z 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>
Implementacja Java DOM do akceptowania powyższego XML jako łańcucha i usuwania deklaracji 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; }
Docelowy XML (bez DTD)
<MYACCSERVICE> <REQ_PAYLOAD> <ACCOUNT>1234567890</ACCOUNT> <BRANCH>001</BRANCH> <CURRENCY>USD</CURRENCY> <TRANS_REFERENCE>201611100000777</TRANS_REFERENCE> </REQ_PAYLOAD> </MYACCSERVICE>
źródło
Jestem podejrzliwy wobec tego stwierdzenia; czy twój dokument zawiera odniesienia do encji? Jeśli tak, zdecydowanie potrzebujesz DTD.
W każdym razie, typowym sposobem zapobiegania takiej sytuacji jest użycie katalogu XML do zdefiniowania ścieżki lokalnej dla „map.dtd”.
źródło
oto inny użytkownik, który napotkał ten sam problem: http://forums.sun.com/thread.jspa?threadID=284209&forumID=34
mówi użytkownik ddssot w tym poście
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; } });
Użytkownik dalej wspomina: „Jak widać, gdy parser trafia w DTD, wywoływany jest mechanizm rozpoznawania jednostek. Rozpoznaję swoje DTD z jego określonym identyfikatorem i zwracam pusty dokument XML zamiast prawdziwego DTD, zatrzymując wszystkie sprawdzanie poprawności ...”
Mam nadzieję że to pomoże.
źródło
Pracuję z sonarqube, a sonarlint dla eclipse pokazał mi, że niezaufany plik XML powinien być analizowany bez rozwiązywania danych zewnętrznych (squid: S2755)
Udało mi się to rozwiązać za pomocą:
factory = DocumentBuilderFactory.newInstance(); factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // If you can't completely disable DTDs, then at least do the following: // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities // JDK7+ - http://xml.org/sax/features/external-general-entities factory.setFeature("http://xml.org/sax/features/external-general-entities", false); // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities // JDK7+ - http://xml.org/sax/features/external-parameter-entities factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); // Disable external DTDs as well factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); // and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks" factory.setXIncludeAware(false); factory.setExpandEntityReferences(false);
źródło