2012-05-23 97 views
0

我有這種方法,它從java.io.InputStream加載一個XHTML文檔,返回一個org.w3c.dom.Document使用DocumentBuilder解析XHTML時出現無限循環「解析」

private Document loadDocFrom(InputStream is) throws SAXException, 
     IOException, ParserConfigurationException { 
    DocumentBuilderFactory domFactory = DocumentBuilderFactory 
      .newInstance(); 
    domFactory.setNamespaceAware(true); // never forget this 
    DocumentBuilder builder = domFactory.newDocumentBuilder(); 

    Document doc = builder.parse(is); 
    is.close(); 
    return doc; 
} 

此方法,我有一些XHTML文檔(例如http://pastebin.com/L2kHwggU)和XHTML網站進行了測試。

但是,對於某些文檔,例如此http://pastebin.com/v675yWSJ甚至像www.w3.org這樣的網站,它會在Document doc = builder.parse(is);處進入無限循環。

編輯:

@邁克爾凱發現了這個問題,但我在等待他的解決方案。

一個其他可能的解決方案是忽略DTD:

domFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false) 

謝謝您的幫助。

+0

你確定循環是無限的嗎?大多數模板處理語言爲每個感興趣的標記發出事件。如果你在事件列表中有一箇中斷點,你可能會有很多令牌可以通過。 – nsfyn55

+0

我沒有添加任何「事件」到該「事件列表」,實際上,我從來沒有聽說過它。那麼你如何解釋我可以解析一些XHTML文檔,如http://pastebin.com/L2kHwggU? 另外,我調試了源代碼,並且一步一步地將它始終卡在那一行「next()」。 – anahnarciso

+0

它沒有在源代碼中的調試語句永遠運行嗎? – nsfyn55

回答

1

我認爲你的診斷是無限循環是不正確的;這只是需要很長時間,這不是一回事。

通常的原因是該文檔在W3C網站上包含對XHTML DTD的引用,並且解析器將轉到Web以獲取該文件而不是使用本地副本。大約一年前,W3C開始對這些常見的DTD進行「限制」請求,因爲它們不能再處理流量。

通常的解決方案是使用解析器將請求重定向到本地副本。

+0

你能告訴我如何使用解析器將請求重定向到本地副本嗎?一個朋友告訴我,我可以「忽略」使用這一行的驗證: 'domFactory.setFeature(「http://apache.org/xml/features/nonvalidating/load-external-dtd」,false);' 它的工作原理,但忽略它是否「正確」? – anahnarciso

+0

該方法可能適用於某些解析器和一些DTD。通常,儘管DTD可能包含實體定義,並且如果主文檔引用了實體定義,那麼它們需要加載。恐怕我從來不使用DOM生成器,所以我不確定如何使它與解析器一起工作,但我知道它可以完成。 –