2010-09-09 12 views
6

Estoy copiando el código de una parte de nuestra aplicación (un applet) dentro de la aplicación. Estoy analizando XML como una cadena. Ha pasado un tiempo desde que analicé XML, pero a partir del error que se arroja, parece que podría tener que ver con no encontrar el .dtd. El seguimiento de la pila hace que sea difícil encontrar la causa exacta del error, pero aquí está el mensaje:¿Por qué recibo "MalformedURLException: no protocol" cuando uso SAXParser?

java.net.MalformedURLException: no protocol: <a href="http://www.mycomp.com/MyComp.dtd">http://www.mycomp.com/MyComp.dtd</a> 

y el XML tiene esto como el primer par de líneas:

<?xml version='1.0'?> 
<!DOCTYPE MYTHING SYSTEM '<a href="http://www.mycomp.com/MyComp.dtd">http://www.mycomp.com/MyComp.dtd</a>'> 

y está el código relevante aquí fragmentos

class XMLImportParser extends DefaultHandler { 

    private SAXParser m_SaxParser = null; 
    private String is_InputString = ""; 

    XMLImportParser(String xmlStr) throws SAXException, IOException { 
    super(); 
    is_InputString = xmlStr; 
    createParser(); 
    try { 
     preparseString(); 
     parseString(is_InputString); 
    } catch (Exception e) { 
     throw new SAXException(e); //"Import Error : "+e.getMessage()); 
    } 
    } 

    void createParser() throws SAXException { 
    SAXParserFactory factory = SAXParserFactory.newInstance(); 
    factory.setValidating(true); 
    try { 
     factory.setFeature("http://xml.org/sax/features/namespaces", true); 
     factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true); 
     m_SaxParser = factory.newSAXParser(); 
     m_SaxParser.getXMLReader().setFeature("http://xml.org/sax/features/namespaces", true); 
     m_SaxParser.getXMLReader().setFeature("http://xml.org/sax/features/namespace-prefixes", true); 
    } catch (SAXNotRecognizedException snre){ 
     throw new SAXException("Failed to create XML parser"); 
    } catch (SAXNotSupportedException snse) { 
     throw new SAXException("Failed to create XML parser"); 
    } catch (Exception ex) { 
     throw new SAXException(ex); 
    } 
    } 

    void preparseString() throws SAXException { 
    try { 
     InputSource lSource = new InputSource(new StringReader(is_InputString)); 
     lSource.setEncoding("UTF-8"); 
     m_SaxParser.parse(lSource, this); 
    } catch (Exception ex) { 
     throw new SAXException(ex); 
    } 
    } 

} 

parece que el error está ocurriendo en el método preparseString(), en la línea que realmente hace el análisis, la línea m_SaxParser.parse(lSource, this);.

Para su información, el archivo 'MyComp.dtd' existe en esa ubicación y se puede acceder a través de http. El archivo XML proviene de un servicio diferente en el servidor, por lo que no puedo cambiarlo a formato file: // y poner el archivo .dtd en classpath.

Respuesta

4

Creo que tiene algún código adicional en la declaración XML. Prueba esto:

<?xml version='1.0'?> 
<!DOCTYPE MYTHING SYSTEM "http://www.mycomp.com/MyComp.dtd"> 

Lo anterior fue capturado de las Recomendaciones del W3C: http://www.w3.org/QA/2002/04/valid-dtd-list.html

Puede utilizar el enlace http para establecer el esquema de la SAXParserFactory antes de crear el analizador.

void createParser() throws SAXException { 
    Schema schema = SchemaFactory.newSchema(new URL("http://www.mycomp.com/MyComp.dtd")); 
    SAXParserFactory factory = SAXParserFactory.newInstance(); 
    factory.setValidating(true); 
    factory.setSchema(schema); 
+0

Gracias por la rápida respuesta. Creo que esta es la respuesta más completa con la etiqueta DOCTYPE corregida completa. Consulte mi pregunta anterior sobre la posibilidad de ignorar esta etiqueta DOCTYPE ya que la obtengo de una fuente externa. – user26270

+0

gracias por las respuestas rápidas – user26270

+0

Puede establecer el esquema en SAXParserFactory en uno creado a partir del enlace http. Publicaré una edición a la respuesta anterior. –

4

El problema es que esto:

<a href="http://www.mycomp.com/MyComp.dtd">http://www.mycomp.com/MyComp.dtd</a> 

es un hipervínculo HTML, no una URL. Reemplazarlo con esto:

http://www.mycomp.com/MyComp.dtd 
+0

Gracias, eso fue todo. Tenía una copia local del Xml y lo cambié. Sin embargo, cuando se ejecuta en vivo, no puedo modificar esta línea DOCTYPE porque la obtengo de un servicio externo. Entonces, ¿hay alguna manera de decirle al analizador que lo ignore? Veo referencias a la validación/no validación en otras partes del código que me preguntan si la no validación lo haría ignorar la mala referencia dtd. – user26270

+0

Al configurar su analizador sintáctico para que no valide, se ignorará todo el DTD. La razón para tener el DTD es para que el analizador pueda validar el XML de entrada en su contra. –

+0

@ codeman73 - debe intentar obtener lo que le está dando que DOCTYPE solucionó. Es claramente falso. –

1

Desde este XML proviene de una fuente externa, la primera cosa a hacer sería a quejarse a ellos que están enviando XML válido.

Como solución alternativa, se puede establecer una EntityResolver en su programa de análisis que compara la SystemId a esta URL no válida y devuelve una correcta URL http:

m_SaxParser.getXMLReader().setEntityResolver(
    new EntityResolver() { 
     public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException { 
      if ("<a href=\"http://www.mycomp.com/MyComp.dtd\">http://www.mycomp.com/MyComp.dtd</a>".equals(systemId)) { 
       return new InputSource("http://www.mycomp.com/MyComp.dtd"); 
      } else { 
       return null; 
      } 
     } 
    } 
); 
Cuestiones relacionadas