У меня есть 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?




Когда ты делаешь
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);