Cuando analizo mi archivo xml (variable f) en este método, aparece un error
C: \ Documents and Settings \ joe \ Desktop \ aicpcudev \ OnlineModule \ map.dtd (El sistema no puede encontrar la ruta especificada)
Sé que no tengo el dtd ni lo necesito. ¿Cómo puedo analizar este objeto Archivo en un objeto Documento sin tener en cuenta los errores de referencia de 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;
}
Respuestas:
Un enfoque similar al sugerido por @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; } } });
Descubrí que simplemente devolver un InputSource vacío funcionaba igual de bien.
fuente
Intente configurar funciones en 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 última instancia, creo que las opciones son específicas de la implementación del analizador. Aquí hay algo de documentación para Xerces2 si eso ayuda.
fuente
load-external-dtd
) me hizo el truco - gracias.dbf.setNamespaceAware(true);
load-external-dtd
escenario fue suficiente.Encontré un problema en el que el archivo DTD estaba en el archivo jar junto con el XML. Resolví el problema en base a los ejemplos aquí, de la siguiente manera: -
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; } } });
fuente
XML de origen (con 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>
Implementación de DOM de Java para aceptar XML anterior como cadena y eliminar la declaración 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 destino (sin DTD)
<MYACCSERVICE> <REQ_PAYLOAD> <ACCOUNT>1234567890</ACCOUNT> <BRANCH>001</BRANCH> <CURRENCY>USD</CURRENCY> <TRANS_REFERENCE>201611100000777</TRANS_REFERENCE> </REQ_PAYLOAD> </MYACCSERVICE>
fuente
Sospecho de esta declaración; ¿Su documento contiene referencias a entidades? Si es así, definitivamente necesita el DTD.
De todos modos, la forma habitual de evitar que esto suceda es utilizando un catálogo XML para definir una ruta local para "map.dtd".
fuente
aquí hay otro usuario que tuvo el mismo problema: http://forums.sun.com/thread.jspa?threadID=284209&forumID=34
el usuario ddssot en esa publicación dice
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; } });
El usuario menciona además: "Como puede ver, cuando el analizador llega al DTD, se llama al solucionador de entidades. Reconozco mi DTD con su ID específico y devuelvo un documento XML vacío en lugar del DTD real, deteniendo toda validación ..."
Espero que esto ayude.
fuente
Estoy trabajando con sonarqube, y sonarlint para eclipse me mostró que XML que no es de confianza debe analizarse sin resolver datos externos (squid: S2755)
Logré resolverlo usando:
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);
fuente