2010-09-09 5 views
6

Je copie du code d'une partie de notre application (une applet) à l'intérieur de l'application. J'analyse XML en tant que chaîne. Cela fait un moment que j'ai analysé XML, mais de l'erreur qui a été lancée, il semblerait que cela puisse être dû au fait de ne pas trouver le fichier .dtd. La trace de la pile rend difficile de trouver la cause exacte de l'erreur, mais voici le message:Pourquoi est-ce que je reçois "MalformedURLException: no protocol" lors de l'utilisation de SAXParser?

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

et le XML a ce que les premières lignes de couple:

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

et est ici le code correspondant snippets

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

} 

Il semble que l'erreur se produit dans la méthode preparseString(), sur la ligne qui ne fait l'analyse syntaxique, la ligne m_SaxParser.parse(lSource, this);.

FYI, le fichier 'MyComp.dtd' existe à cet emplacement et est accessible via http. Le fichier XML provient d'un service différent sur le serveur, donc je ne peux pas le changer en format file: // et mettre le fichier .dtd sur le classpath.

Répondre

4

Je pense que vous avez du code supplémentaire dans la déclaration XML. Essayez ceci:

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

Ce qui précède a été capturé par les recommandations du W3C: http://www.w3.org/QA/2002/04/valid-dtd-list.html

Vous pouvez utiliser le lien http pour définir le schéma sur la SAXParserFactory avant de créer votre analyseur.

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

Merci pour la réponse rapide. Je pense que c'est la réponse la plus complète avec l'étiquette DOCTYPE corrigée complète. S'il vous plaît voir ma question ci-dessus sur la possibilité d'ignorer cette étiquette DOCTYPE depuis que je l'obtiens d'une source externe. – user26270

+0

merci pour les réponses rapides – user26270

+0

Vous pouvez définir le schéma sur le SAXParserFactory à un créé à partir du lien http. Je posterai un edit à la réponse ci-dessus. –

4

Le problème est que ceci:

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

est un lien hypertexte HTML, pas une URL. Remplacez-le par ceci:

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

Merci, ça l'a fait. J'ai eu une copie locale du Xml et l'ai changé. Cependant, lors de l'exécution en direct, je ne peux pas modifier cette ligne DOCTYPE parce que je l'obtiens d'un service externe. Alors, y a-t-il un moyen de dire à l'analyseur de l'ignorer? Je vois des références à la validation/non-validation dans d'autres parties du code qui me font me demander si la non-validation le ferait ignorer la mauvaise référence dtd. – user26270

+0

Si vous ne validez pas votre analyseur, la DTD entière sera ignorée. La raison d'avoir la DTD est telle que l'analyseur peut valider le XML d'entrée par rapport à celui-ci. –

+0

@ codeman73 - vous devriez essayer d'obtenir ce qui vous donne ce DOCTYPE corrigé. C'est clairement faux. –

1

Depuis ce XML provient d'une source externe, la première chose à faire serait de les plaindre à ce qu'ils envoient XML non valide.

Pour contourner ce problème, vous pouvez définir une EntityResolver sur votre analyseur qui compare le SystemId à cette URL invalide et renvoie une URL correcte 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; 
      } 
     } 
    } 
); 
Questions connexes