Perché mi appare “MalformedURLException: nessun protocollo” quando si usa SAXParser?

StackOverflow https://stackoverflow.com/questions/3677517

  •  01-10-2019
  •  | 
  •  

Domanda

Sto copiando il codice da una parte della nostra applicazione (un applet) per all'interno della app. Sto parsing XML come una stringa. E 'stato un po' da quando ho analizzato XML, ma dall'errore che ha gettato sembra che potrebbe avere a che fare con non trovare il .dtd. L'analisi dello stack rende difficile trovare la causa esatta dell'errore, ma ecco il messaggio:

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

e l'XML ha questo come il primo paio di righe:

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

ed ecco i frammenti di codice rilevanti

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);
    }
  }

}

Sembra che l'errore sta accadendo nel preparseString () il metodo, sulla linea che in realtà fa il parsing, la linea m_SaxParser.parse(lSource, this);.

Cordiali saluti, il file 'MyComp.dtd' esiste in quella posizione ed è accessibile tramite http. Il file XML viene da un servizio diverso sul server, quindi non posso cambiarlo in un file: // formato e mettere il file .dtd nel classpath.

È stato utile?

Soluzione

Penso che tu abbia un po 'di codice aggiuntivo nella dichiarazione XML. Prova questo:

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

È possibile che questo è stato catturato dalle Raccomandazioni del W3C: http: //www.w3.org/QA/2002/04/valid-dtd-list.html

È possibile utilizzare il link http per impostare lo schema sul SAXParserFactory prima di creare il parser.

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);

Altri suggerimenti

Il problema è che questo:

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

è un collegamento ipertestuale HTML, non un URL. Sostituirla con questo:

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

Dal momento che questo XML proviene da una fonte esterna, la prima cosa da fare sarebbe quella di lamentarsi con loro che stanno inviando XML non valido.

Per risolvere il problema, è possibile impostare un EntityResolver sul parser che mette a confronto lo systemID a questo URL non valido e restituisce un corretto 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;
            }
        }
    }
);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top