Указание DTD для использования DocumentBuilders для разбора XML? - PullRequest
0 голосов
/ 22 сентября 2011

В настоящее время я пишу инструмент, использующий Java 1.6, который объединяет несколько файлов XML. Все файлы проверяются на DocBook 4.5 DTD (я проверил это, используя xmllint и указав DocBook 4.5 DTD в качестве параметра --dtdvalid), но не все из них включают объявление DOCTYPE.

Я загружаю каждый XML-файл в DOM для выполнения необходимых манипуляций следующим образом:

private Document fileToDocument( File input ) throws ParserConfigurationException, IOException, SAXException {

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

    factory.setNamespaceAware(true);
    factory.setIgnoringElementContentWhitespace(false);
    factory.setIgnoringComments(false);
    factory.setValidating(false);
    factory.setExpandEntityReferences(false);

    DocumentBuilder builder = factory.newDocumentBuilder();
    return builder.parse( input );

}

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

  • Не включать декларацию DOCTYPE и
  • Включать объекты, определенные в DTD (например, & mdash; / & mdash;).

В этом случае исключение выдается из вызова builder.parse (...) с сообщением:

[Fatal Error] :5:15: The entity "mdash" was referenced, but not declared.

Достаточно справедливо, это не объявлено. В этом случае я бы идеально настроил DocumentBuilderFactory на использование DTD DocBook 4.5 независимо от того, указан ли он в файле.

Я попытался выполнить проверку с использованием схемы DocBook 4.5, но обнаружил, что это привело к ряду несвязанных ошибок с XML. Кажется, что схема не может быть функционально эквивалентна DTD, по крайней мере, для этой версии спецификации DocBook.

Другой вариант, о котором я могу подумать, - это прочитать файл, попытаться определить, был ли установлен тип документа или нет, а затем установить его, если ничего не было найдено до фактического анализа XML в DOM.

Итак, мой вопрос: есть ли более умный способ, который я не видел, чтобы сказать парсеру использовать определенный DTD или гарантировать, что синтаксический анализ продолжается, несмотря на то, что сущности не разрешаются (не только в примере & emdash; XML - есть большое количество потенциалов)?

1 Ответ

1 голос
/ 22 сентября 2011

Может ли использовать EntityResolver2 и реализовать EntityResolver2.getExternalSubset () help?

... Этот метод также можно использовать с документами, в которых нет объявления DOCTYPE. Когда встречается корневой элемент, но объявление DOCTYPE не обнаружено, вызывается этот метод. Если он возвращает значение для внешнего подмножества, этот корневой элемент объявляется корневым элементом, давая эффект соединения объявления DOCTYPE в конце пролога документа, который иначе не мог бы быть действительным. ...

...