2010-09-09 78 views
6

我正在從我們的應用程序的一部分(一個小程序)到應用程序內部複製代碼。我將XML解析爲字符串。自從我解析XML以來已經有一段時間了,但是從拋出的錯誤看來,它可能與找不到.dtd有關。堆棧跟蹤使得它很難找到錯誤的確切原因,但這裏的消息:爲什麼在使用SAXParser時會出現「MalformedURLException:no protocol」?

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

和XML有這個作爲第一個兩行:

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

和這裏的相關代碼網頁摘要

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

} 

它看起來像錯誤是在preparseString()方法中發生的事情,在實際執行解析線,m_SaxParser.parse(lSource, this);線。

僅供參考,'MyComp.dtd'文件確實存在於該位置並可通過http訪問。 XML文件來自服務器上的其他服務器,因此我無法將其更改爲file://格式,並將.dtd文件放在類路徑中。

回答

4

我想你在XML聲明中有一些額外的代碼。試試這個:

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

以上是來自W3C的建議捕獲:http://www.w3.org/QA/2002/04/valid-dtd-list.html

您可以使用HTTP鏈接創建解析器之前設置上的SAXParserFactory架構。

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

感謝您的快速反應。我認爲這是完整的DOCTYPE標籤更完整的答案。請看我上面的問題,關於忽略這個DOCTYPE標籤的可能性,因爲我從外部獲取它。 – user26270 2010-09-09 14:47:12

+0

感謝您的快速解答 – user26270 2010-09-09 15:09:17

+0

您可以將SAXParserFactory上的Schema設置爲從http鏈接創建的Schema。我會在上面的答案上發佈一個修改。 – 2010-09-09 15:12:52

4

的問題是這樣的:

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

是一個HTML超鏈接,而不是URL。這種替換:

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

謝謝,就是這樣。我有一個Xml的本地副本並對其進行了更改。但是,在運行時,我無法修改此DOCTYPE行,因爲我從外部服務獲取它。那麼有什麼辦法可以告訴解析器忽略它嗎?我在代碼的其他部分看到了驗證/非驗證的參考信息,這讓我懷疑是否驗證會使其忽略不良的dtd參考。 – user26270 2010-09-09 14:45:47

+0

將分析器設置爲不驗證會導致整個DTD被忽略。擁有DTD的原因是,解析器可以根據它來驗證輸入XML。 – 2010-09-09 15:07:54

+0

@ codeman73 - 你應該嘗試得到任何給你的DOCTYPE固定的東西。這顯然是假的。 – 2010-09-09 15:22:53

1

由於這個XML來自外部源,要做的第一件事將是抱怨他們,他們正在發送無效的XML。

作爲一種變通方法,您可以設置您的解析器EntityResolver的SYSTEMID比較這個無效的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; 
      } 
     } 
    } 
); 
相關問題