2012-05-23 71 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生成器,所以我不确定如何使它与解析器一起工作,但我知道它可以完成。 –