【问题标题】:Xerces DOM parser incredibly slow?Xerces DOM 解析器非常慢?
【发布时间】:2011-12-18 21:29:11
【问题描述】:

目前,我正在尝试使用 JTidy 清理 HTML 文件,将其转换为 XHTML 并将结果提供给 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。

提前感谢您对此提出的任何建议!

【问题讨论】:

  • 很奇怪。在这么小的文件上不应该这么慢。而且由于您将验证明确设置为 false,我不希望它能够解决 DTD 中的问题。您可以通过分析器运行它以找出哪些调用花费的时间最多?

标签: java performance dom xerces


【解决方案1】:

即使不进行验证,XML 解析器也需要获取 DTD,例如支持命名字符实体。您应该考虑实现一个 EntityResolver,它将对 DTD 的请求解析为本地副本。

【讨论】:

  • 这是问题所在...我已经通过分析器运行了代码,并且 98.9% 的执行时间(总计 120 秒)花费在 java.net.SocketInputStream.read 中。这又源自HttpURLConnection,它是由来自JRE 的内部Xerces 解析器的XMLDTDScannerImpl 创建的。即使禁用了标准 DTD 验证,它仍然需要那些实体声明。我自己从未使用过 DTD(总是本地可用的模式)。 +1
  • 您的建议是正确的,我只是在我的示例中验证了它。为方便起见,Xerces 允许使用功能设置禁用 DTD 获取:factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); 感谢您的快速帮助!
  • 查看xerces.apache.org/xerces2-j/features.html了解其他可用功能。
【解决方案2】:

HTML dtd 很大,使用包含。他们需要永远。使用XML catalog。可以在本地存储 dtds 并通过系统 ID 映射它们。

如果你使用一个工具,比如maven,你会发现足够多的指针。

优势 i.o.正如公认的答案所暗示的那样,拦截实体是您收到正确的字符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-31
    • 2016-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    • 2010-11-24
    • 1970-01-01
    相关资源
    最近更新 更多