Ужасная производительность при разборе файла XHTML с Doctype как XML-документ - PullRequest
3 голосов
/ 09 марта 2012

Когда я анализирую этот файл xhtml как xml, анализ такого простого файла занимает около 2 минут. Я обнаружил, что если я удаляю объявление типа документа, оно мгновенно анализируется. Что плохого в том, что этот файл так долго анализируется?

Пример Java

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware( true );
DocumentBuilder bob = dbf.newDocumentBuilder();
Document template = bob.parse( new InputSource( new FileReader( xmlFile ) ) );

Пример XHTML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ex="http://www.example.com/schema/v1_0_0">
    <head><title>Test</title></head>
    <body>
        <h1>Test</h1>
        <p>Hello, World!</p>
        <p><ex:test>Text</ex:test></p>
    </body>
</html>

Спасибо

Редактировать: Решение

Чтобы на самом деле решить проблему на основе предоставленной информации о том, почему она вообще произошла, я сделал следующие основные шаги:

  1. Загруженные файлы, связанные с DTD, в папку src / main / resources
  2. Создал пользовательский EntityResolver для чтения этих файлов из classpath
  3. Сказал моему DocumentBuilder использовать мой новый EntityResolver

Я ссылался на этот SO-ответ при этом: Как проверить XML с помощью Java?

Новый EntityResolver

import java.io.IOException;

import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class LocalXhtmlDtdEntityResolver implements EntityResolver {

    /* (non-Javadoc)
     * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, java.lang.String)
     */
    @Override
    public InputSource resolveEntity( String publicId, String systemId )
            throws SAXException, IOException {
        String fileName = systemId.substring( systemId.lastIndexOf( "/" ) + 1 );    
        return new InputSource( 
                getClass().getClassLoader().getResourceAsStream( fileName ) );
    }

}

Как использовать новый EntityResolver:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware( true );
DocumentBuilder bob = dbf.newDocumentBuilder();
bob.setEntityResolver( new LocalXhtmlDtdEntityResolver() );
Document template = bob.parse( new InputSource( new FileReader( xmlFile ) ) );

Ответы [ 2 ]

3 голосов
/ 09 марта 2012

Java загружает указанный DTD и включенные в него файлы, чтобы проверить, что ваш файл xhtml подчиняется указанному DTD.Используя прокси-сервер Charles, я записал следующие запросы, загружая указанные суммы:

2 голосов
/ 09 марта 2012

На самом деле, вам повезло, что вы получили документы вообще.W3C сознательно не отвечает на запросы этих документов, потому что они не могут обработать объем запросов.Вам нужно предоставить синтаксическому анализатору локальную копию.

Обычный способ сделать это в мире Java - использовать средства преобразования каталога Apache / Oasis.

Последняя версия Saxon обладает встроенными знаниями об этих обычно используемых DTD и файлах сущностей, и если вы разрешите Saxon предоставлять ваш XML-анализатор, он автоматически настроится на использование локальных копий.Вероятно, вы можете воспользоваться этим, даже если вы не используете XSLT или XQuery для обработки данных: просто создайте объект Saxon Configuration и вызовите его метод getSourceParser (), чтобы получить XMLReader.

(возможно, это будетхорошо бы также отучиться от DOM. Из всех многочисленных вариантов обработки XML в Java DOM, вероятно, является худшим. Если вам необходимо использовать низкоуровневый навигационный API, выберите подходящий, например JDOM или XOM.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...