parseo node manage leer java document dtd

java - node - Haga que DocumentBuilder.parse ignore las referencias de DTD



parseo de xml en java (6)

Sé que no tengo el dtd, ni lo necesito.

Sospecho de esta declaración; ¿su documento contiene referencias de entidades? Si es así, definitivamente necesitas la DTD.

De todos modos, la forma habitual de evitar que esto suceda es utilizar un catálogo XML para definir una ruta local para "map.dtd".

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 File en un objeto Document mientras ignoro los errores de referencia 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; }


Aquí hay otro usuario que tiene el mismo problema: http://forums.sun.com/thread.jspa?threadID=284209&forumID=34

ddssot de usuario 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 toca la DTD, se invoca la resolución de la entidad. Reconozco mi DTD con su ID específica y devuelvo un documento XML vacío en lugar de la DTD real, deteniendo toda la validación ..."

Espero que esto ayude.


Encontré un problema donde 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; } } });


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 definitiva, creo que las opciones son específicas para la implementación del analizador. Aquí hay documentación para Xerces2 si eso ayuda.


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 XML (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 Java DOM para aceptar el 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>