Запретить загрузку DTD при использовании XSLT, т.е. XML Transformer

Я должен обрабатывать XML-файлы, которые имеют DTD с XSLT в Java. DTD действительно необходим, потому что он содержит определения сущностей, которые я использую. (в сторону: да, использование сущностей для вещей, которые могут использовать Unicode - плохая идея;-)

Когда я запускаю преобразование, он каждый раз загружает DTD из внешнего источника. Я хочу использовать каталог XML для кэширования DTD, поэтому я дал TransformerFactory CatalogResolver как URIResolver:

URIResolver cr = new CatalogResolver();
tf = TransformerFactory.newInstance();
tf.setURIResolver(cr);
Transformer t = tf.newTransformer(xsltSrc);
t.setURIResolver(cr);
Result res = new SAXResult(myDefaultHandler());
t.transform(xmlSrc, res);

Но когда я запускаю преобразование, он все равно загружает DTD по сети. (Использование Xalan и Xerces либо в составе Java5, либо в автономном режиме, либо использование Saxon и Xerces.)

Что нужно, чтобы преобразование использовало только локальную копию DTD?

2 ответа

Решение

(Я отвечаю на свой вопрос здесь, чтобы спасти меня в следующий раз, или кому-то еще, в те дни, когда мне нужно было найти ответ.)

Что действительно нужно, чтобы изменить способ разрешения DTD, так это EntityResolver, К сожалению, невозможно установить EntityResolver быть использованным Transformer, Таким образом, вы должны создать XMLReader сначала с CatalogResolver как его EntityResolver:

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
XMLReader r = spf.newSAXParser().getXMLReader();
EntityResolver er = new CatalogResolver();
r.setEntityResolver(er);

и использовать его для Transformer:

SAXSource s = new SAXSource(r, xmlSrc);
Result res = new SAXResult(myDefaultHandler());
transformer.transform(s, res);

Вы можете использовать этот код для отключения такой функциональности в Xerces:

org.dom4j.io.SAXReader reader = new org.dom4j.io.SAXReader();
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

В этом примере кода используется Dom4j, но аналогичные функции setFeature существуют в других библиотеках XML Java, таких как JDOM.

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