Как включить DTD в XML-файл, который будет загружен с помощью getResourceAsStream ()?

У меня есть XML-файл ('videofaq.xml'), который определяет DTD, используя следующий DOCTYPE

<!DOCTYPE video-faq SYSTEM "videofaq.dtd">

Я загружаю файл из пути к классам (на самом деле из JAR) во время инициализации сервлета, используя:

getClass().getResourceAsStream("videofaq.xml")

XML найден правильно, но для DTD в том же пакете Xerces дает мне исключение FileNotFoundException и отображает путь к сценарию запуска Tomcat с добавлением «videofaq.dtd» в конец. Какие подсказки, если они есть, я могу передать Xerces, чтобы он правильно загрузил DTD?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
2 858
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Когда ты делаешь

getClass().getResourceAsStream("videofaq.xml")

Это не xerces, который вы вызываете, и поэтому, когда вы передаете поток xerces, он не может знать, откуда загружается файл. Он загружает его из корневого пути приложения (который вы описали).

Простым решением было бы указать в вашем XML-файле полный путь к файлу dtd.

Кроме того, xerces, похоже, пробует несколько мест. Поэтому вам следует взглянуть на механизм кэширования грамматики или преобразователи сущностей (которые, я думаю, используются в таком порядке).

Грамматический документ Xerces: http://xerces.apache.org/xerces2-j/faq-grammars.html

Функции Xerces use-entity-resolver2: http://xerces.apache.org/xerces2-j/features.html

При использовании SAX вы можете предоставить свой собственный EntityResolver, который затем загружает ресурс любым удобным для вас способом.

В общем, старайтесь использовать перегрузки методов, которые принимают URL-адрес (обычно в виде строки с именем параметра, например "systemId"), при указании ввода для синтаксического анализатора XML. Это позволяет синтаксическому анализатору разрешать относительные ссылки за вас и предоставлять более точные сообщения об ошибках.

Итак, в вашем случае найдите DTD в том же пакете с videofaq.xml и передайте результат String для getClass().getResource("videofaq.xml") синтаксическому анализатору XML.

Ответ принят как подходящий

Пользовательский EntityResolver будет работать, но вы можете избежать создания пользовательского класса, установив SystemID, позволяющий процессору «находить» относительные пути.

http://www.onjava.com/pub/a/onjava/excerpt/java_xslt_ch5/index.html?page=5

By providing a system identifier as a parameter to the StreamSource, you are telling the XSLT processor where to look for commonFooter.xslt. Without this parameter, you may encounter an error when the processor cannot resolve this URI. The simple fix is to call the setSystemId( ) method as follows:

// construct a Source that reads from an InputStream
Source mySrc = new StreamSource(anInputStream);
// specify a system ID (a String) so the 
// Source can resolve relative URLs
// that are encountered in XSLT stylesheets
mySrc.setSystemId(aSystemId);

Другие вопросы по теме