#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
в. Это, в свою очередь, происходит от aHttpURLConnection
, который создаетсяXMLDTDScannerImpl
из внутреннего анализатора Xerces JRE. Даже при отключенной стандартной проверке DTD ему все равно понадобятся эти объявления сущностей. Никогда не использовал DTD сам (всегда локально доступные схемы). 12. Ваше предложение верно, я только что проверил его в своем примере. Для удобства 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, вы найдете достаточно указателей.
Преимущество ввода-вывода, перехватывающего объекты, как следует из принятого ответа, заключается в том, что вы получаете правильные символы.