Запретить загрузку 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.