Проверить и проанализировать xml с помощью woodstox с локальным dtd

Я видел несколько вопросов, связанных с синтаксическим анализом XML-файлов с использованием woodstox и JAXB для демаршалирования с использованием XMLStreamReader и проверки по схемам. Чтение их не помогло. Что мне нужно, так это проверить входящий xml с помощью локального DTD и проанализировать все содержимое в объектном представлении. Входящий xml может иметь DOCTYPE, который включает DTD. Это нужно пропустить и вместо этого использовать локальный DTD. Реализация должна быть очень быстрой. Ожидается ‹ 1 мс для проверки и синтаксического анализа. Мне удалось разобрать в одиночку, используя следующее за 5 мс. Включение проверки не работает с настройкой схемы (закомментированные строки кода)

xmlif = XMLInputFactory2.newInstance();
    xmlif.setProperty(XMLInputFactory2.SUPPORT_DTD, false);
    JAXBContext ucontext;
    ucontext = JAXBContext.newInstance(XMLOuterElementClass.class);
    unmarshaller = ucontext.createUnmarshaller();
    /*SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.XML_DTD_NS_URI);
    Schema schema = sf.newSchema(new File("c:/resources/schma.dtd"));
    unmarshaller.setSchema(schema);*/

XMLStreamReader xsr = xmlif
                .createXMLStreamReader(new StringReader(xml));
        //xsr = new StreamReaderDelegate(xsr);
        long start = System.currentTimeMillis();

        try {
            while (xsr.hasNext()) {
                if (xsr.isStartElement()
                        && xsr.getLocalName() == "XMLOuterElementClass") {
                    break;
                }
                xsr.next();
            }
            JAXBElement<XMLOuterElementClass> jb = unmarshaller.unmarshal(xsr,
                XMLOuterElementClass.class);
            System.out.println("Total time taken in ms :" + (end - start));

        } finally {
            xsr.close();
        }

person Ajay    schedule 21.08.2013    source источник


Ответы (1)


Есть несколько способов сделать это; и лучший способ получить более подробный ответ — задать его в списке пользователей Woodstox (см. http://xircles.codehaus.org/projects/woodstox/lists).

Но следует отметить, что JAXB ничего не знает о Stax2 (расширение Woodstox/Aalto по сравнению с базовым Stax), поэтому вам нужно получить к нему доступ через API Stax2, а не JAXB. Итак, чтобы включить «внешнюю» проверку, вам нужно вызвать:

xmlStreamReader2.validateAgainst(schemaFromDTD);

и вы можете сделать это сразу после создания потокового считывателя (необходимо привести к XMLStreamReader2 или, по крайней мере, к Validatable). Обратите внимание, что вы можете проверять при чтении ИЛИ записи, оба работают одинаково (в последнем случае вы включаете его через XMLStreamWriter).

Другой возможностью является определение свойства XMLResolver (см. XMLInputFactory.RESOLVER). Он вызывается при попытке прочитать внешний dtd, то есть когда DOCTYPE содержит ссылку на внешний файл. Пользовательский XMLResolver может затем перенаправить это чтение, чтобы использовать какой-либо другой источник.

Обратите внимание, что первый подход (тот, с которого вы начали), вероятно, более эффективен, поскольку ему нужно только один раз прочитать и проанализировать схему, предполагая, что вы прочитали ее один раз и впоследствии использовали повторно. Сама проверка должна быть быстрой, и если синтаксический анализ занимает 4 миллисекунды, не должен занимать более 1 миллисекунды; особенно если вы включаете обработку JAXB за 4 миллисекунды (это технически привязка данных, выше синтаксического анализа более низкого уровня).

person StaxMan    schedule 21.08.2013
comment
Спасибо за указатель. Попробую список пользователей. Доведение времени проверки и синтаксического анализа до ‹ 1 мс кажется почти непрактичным. - person Ajay; 21.08.2013
comment
На самом деле зависит от размера контента; разбор XML может выполняться со скоростью 10-40 мегабайт в секунду, в зависимости от парсера. Таким образом, за 1 мс вы сможете обрабатывать документы размером 10–40 КБ. Но накладные расходы JAXB более проблематичны. Также убедитесь, что ВСЕГДА повторно используете XMLInputFactory - person StaxMan; 21.08.2013
comment
Хм, это дает надежду попробовать. Я поделюсь своими выводами, если мне удастся проверить и проанализировать в ожидаемые сроки. Кроме того, когда вы говорите, что синтаксический анализ возможен за 1 мс, ожидайте, что он будет анализировать весь контент, а не только интересующий вас раздел. - person Ajay; 22.08.2013
comment
Верный; синтаксический анализ всего содержимого - даже при пропуске парсеры должны выполнять большую часть работы (проверка правильности, например правильности имени, уникальности имени атрибута, вложенности, раскрытия объекта). - person StaxMan; 22.08.2013
comment
Просто хотел сообщить, что woodstox действительно дал ожидаемые результаты, и по приведенной выше постановке задачи, которая была частью конкурса, мы в итоге выиграли первыми :) - person Ajay; 20.02.2014
comment
@Аджай Отлично! Спасибо за обновление и рад, что все получилось, как и ожидалось. - person StaxMan; 25.02.2014