Анализатор Xerces DOM невероятно медленный?

#java #performance #dom #xerces

#java #Производительность #дом #xerces #dom

Вопрос:

В настоящее время я пытаюсь очистить HTML-файл с помощью JTidy, преобразовать его в 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.

Заранее спасибо за любые предложения по этому вопросу!

Комментарии:

1. Очень странно. Не должно быть где-то рядом с этим медленным в таком маленьком документе. И поскольку вы явно установили для проверки значение false, я бы не ожидал, что он разрешит проблемы из DTD. Можете ли вы запустить это через профилировщик, чтобы выяснить, какие вызовы занимают больше всего времени?

Ответ №1:

Даже если проверка не выполняется, анализатор XML должен извлекать DTD, например, для поддержки именованных символьных объектов. Вам следует изучить возможность реализации EntityResolver, который разрешает запрос DTD в локальную копию.

Комментарии:

1. В этом проблема… Я прогнал код через профилировщик, и 98,9% времени выполнения (что составляет 120 секунд) было потрачено java.net.SocketInputStream.read в. Это, в свою очередь, происходит от a HttpURLConnection , который создается XMLDTDScannerImpl из внутреннего анализатора Xerces JRE. Даже при отключенной стандартной проверке DTD ему все равно понадобятся эти объявления сущностей. Никогда не использовал DTD сам (всегда локально доступные схемы). 1

2. Ваше предложение верно, я только что проверил его в своем примере. Для удобства Xerces позволяет отключить выборку DTD с помощью настройки функции: factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); Спасибо за быструю помощь!

3. Смотрите xerces.apache.org/xerces2-j/features.html для других доступных функций.

Ответ №2:

HTML dtd огромны, используя includes. Они занимают вечность. Используйте каталог XML. Там можно хранить dtd локально и сопоставлять их по их системному идентификатору.

Если вы используете инструмент, такой как maven, вы найдете достаточно указателей.

Преимущество ввода-вывода, перехватывающего объекты, как следует из принятого ответа, заключается в том, что вы получаете правильные символы.