2011-10-31 70 views
3

目前,我正在嘗試使用JTidy清理HTML文件,將其轉換爲XHTML並將結果提供給DOM解析器。下面的代碼是這些努力的結果:Xerces DOM解析器非常慢?

public class HeaderBasedNewsProvider implements INewsProvider { 

    /* ... */ 

    public Collection<INewsEntry> getNewsEntries() throws NewsUnavailableException { 
      Document document; 
     try { 
      document = getCleanedDocument(); 
     } catch (Exception e) { 
      throw new NewsUnavailableException(e); 
     } 
     System.err.println(document.getDocumentElement().getTextContent()); 
     return null; 
    } 

    private final Document getCleanedDocument() throws IOException, SAXException, ParserConfigurationException { 
     InputStream input = inputStreamProvider.getInputStream(); 
     Tidy tidy = new Tidy(); 
     tidy.setXHTML(true); 
     ByteArrayOutputStream tidyOutputStream = new ByteArrayOutputStream(); 
     tidy.parse(input, tidyOutputStream); 
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     factory.setValidating(false); 
     InputStream domInputStream = new ByteArrayInputStream(tidyOutputStream.toByteArray()); 
     System.err.println(factory.getClass()); 
     return factory.newDocumentBuilder().parse(domInputStream); 
    } 
} 

然而,DOM解析器實現(com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl)在我的系統似乎是慢得令人難以置信。即使對於一個在線文檔,如下面的解析需要2-3分鐘:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title></title></head><body><div class="text"><h2>Nachricht vom 16. Juni 2011</h2><h1>Titel</h1><p>Mitteilung <a href="dokumente/medienmitteilungen/MM_NR_jglp.pdf" target="_blank">weiter</a> mehr Mitteilung</p></div></body></html> 

注意 - 在對比的是DOM解析器 - JTidy完成一秒鐘內工作。因此,我懷疑我在某種程度上濫用了DOM API。

在此先感謝您的任何建議!

+0

很奇怪。在這樣一個小文件上不應該接近那麼慢。而且,由於您明確將驗證設置爲false,因此我不希望它從DTD解析內容。你可以通過一個分析器來查看哪些電話花費最多時間? –

回答

7

即使未驗證,XML解析器也需要獲取DTD,例如以支持命名字符實體。您應該考慮實現一個EntityResolver,該解決方案將DTD請求解析爲本地副本。

+1

這就是問題所在......我通過一個profiler運行了代碼,98.9%的執行時間(達120秒)花在了'java.net.SocketInputStream.read'中。這反過來又來自於HttpURLConnection,該HttpURLConnection由JRE的內部Xerces解析器中的XMLDTDScannerImpl創建。即使標準的DTD驗證被禁用,它仍然需要這些實體聲明。我從來沒有使用DTD(始終是本地可用的模式)。 +1 –

+1

你的建議是正確的,我剛剛在我的例子中驗證了它。爲方便起見,Xerces允許使用功能設置禁用DTD提取: 'factory.setFeature(「http://apache.org/xml/features/nonvalidating/load-external-dtd」,false);' 謝謝快速幫助! –

+0

有關其他可用功能,請參閱http://xerces.apache.org/xerces2-j/features.html。 – PypeBros

2

HTML dtd是巨大的,使用包括。他們需要永遠。使用XML catalog。可以在本地存儲dtds並通過系統ID映射它們。

如果您使用的工具,如maven,你會發現足夠的指針。

優勢i.o.攔截實體作爲接受的答案表明,您收到正確的字符。