Lorsque j'analyse mon fichier xml (variable f) dans cette méthode, j'obtiens une erreur
C:\Documents and Settings\joe\Desktop\aicpcudev\OnlineModule\map.dtd (le système ne peut pas trouver le chemin spécifié)
Je sais que je n'ai pas le dtd et que je n'en ai pas besoin. Comment puis-je analyser cet objet File dans un objet Document tout en ignorant les erreurs de référence 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;
}
Une approche similaire à celle suggérée par @ 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;
}
}
});
J'ai trouvé que le simple retour d'un InputSource vide fonctionnait aussi bien?
Essayez de définir des fonctionnalités sur 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();
...
En fin de compte, je pense que les options sont spécifiques à la mise en œuvre de l'analyseur. Voici une documentation pour Xerces2 si cela aide.
J'ai trouvé un problème où le fichier DTD était dans le fichier jar avec le XML. J'ai résolu le problème sur la base des exemples ici, comme suit: -
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 source (avec 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>
Implémentation Java DOM pour accepter le XML ci-dessus en tant que chaîne et supprimer la déclaration 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 de destination (sans DTD)
<MYACCSERVICE>
<REQ_PAYLOAD>
<ACCOUNT>1234567890</ACCOUNT>
<BRANCH>001</BRANCH>
<CURRENCY>USD</CURRENCY>
<TRANS_REFERENCE>201611100000777</TRANS_REFERENCE>
</REQ_PAYLOAD>
</MYACCSERVICE>
voici un autre utilisateur qui a eu le même problème: http://forums.Sun.com/thread.jspa?threadID=284209&forumID=34
l'utilisateur ddssot sur ce poste dit
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;
}
});
L'utilisateur mentionne en outre "Comme vous pouvez le voir, lorsque l'analyseur atteint la DTD, le résolveur d'entité est appelé. Je reconnais ma DTD avec son ID spécifique et renvoie un document XML vide au lieu de la vraie DTD, arrêtant toute validation ..."
J'espère que cela t'aides.
Je sais que je n'ai pas le dtd et que je n'en ai pas besoin.
Je me méfie de cette déclaration; votre document contient-il des références d'entité? Si c'est le cas, vous avez certainement besoin de la DTD.
Quoi qu'il en soit, la manière habituelle d'empêcher que cela se produise est d'utiliser un catalogue XML pour définir un chemin local pour "map.dtd".