Как использовать dom4j SAXReader в автономном режиме?
Я хотел бы работать с SAXReader в автономном режиме, проблема в том, что SAXReader проверяет XML, соответствующий DTD. Я не хочу менять DTD или что-то еще в XML. В результате поиска на этом сайте и в других источниках я нашел 2 ответа, которые мне не помогли:
- используйте EntityResolver для обхода сетевого вызова
- использовать setIncludeExternalDTDDeclarations(false)
Пример того, что я пытался сделать:
protected Document getPlistDocument() throws MalformedURLException,
DocumentException {
SAXReader saxReader = new SAXReader();
saxReader.setIgnoreComments(false);
saxReader.setIncludeExternalDTDDeclarations(false);
saxReader.setIncludeInternalDTDDeclarations(true);
saxReader.setEntityResolver(new MyResolver());
Document plistDocument = saxReader.read(getDestinationFile().toURI().toURL());
return plistDocument;
}
public class MyResolver implements EntityResolver {
public InputSource resolveEntity (String publicId, String systemId)
{
if (systemId.equals("http://www.myhost.com/today")) {
// if we want a custom implementation, return a special input source
return null;
} else {
// use the default behaviour
return null;
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
Я все еще не могу работать в автономном режиме, пожалуйста, совет... спасибо
Трассировки стека:
14:20:44,358 ERROR [ApplicationBuilder] iphone build failed: Resource Manager - Problem handle Root.plist: www.apple.com Nested exception: www.apple.com
com.something.builder.sourcemanager.exception.SourceHandlingException: Resource Manager - Problem handle Root.plist: www.apple.com Nested exception: www.apple.com
****
****
Caused by: org.dom4j.DocumentException: www.apple.com Nested exception: www.apple.com
at org.dom4j.io.SAXReader.read(SAXReader.java:484)
at org.dom4j.io.SAXReader.read(SAXReader.java:291)
... 10 more
4 ответа
Ваш решатель сущностей ничего не обрабатывает (так как он всегда возвращает ноль). Сделайте так, чтобы он возвращал InputSource к фактическому файлу DTD, когда системный идентификатор http://www.apple.com/DTDs/PropertyList-1.0.dtd
, поскольку это DTD, который dom4j пытается загрузить.
public class MyResolver implements EntityResolver {
public InputSource resolveEntity (String publicId, String systemId)
{
if (systemId.equals("http://www.apple.com/DTDs/PropertyList-1.0.dtd")) {
return new InputSource(MyResolver.class.getResourceAsStream("/dtds/PropertyList-1.0.dtd");
} else {
// use the default behaviour
return null;
}
}
}
Эта реализация, например, возвращает DTD из classpath (в пакете dtds
). Вы просто должны загрузить DTD самостоятельно и связать его в своем приложении, в пакете dtds
,
Обратите внимание, что вы на самом деле не проверяете DTD. Для этого вам необходимо:
SAXReader saxReader = new SAXReader(true);
В остальном JB прав - он получил за 3 минуты до меня!
Как вариант, если вы хотите просто использовать SAXReader в автономном режиме, отключите его внешнюю выборку DTD через http://apache.org/xml/features/nonvalidating/load-external-dtd
Особенность Xerces.
Согласно документации по функциям Xerces, установка этого значения в false заставляет SAXReader полностью игнорировать внешний DTD.
Этот SO ответ имеет пример кода.
Я использую NoOpEntityResolver для отключения онлайн dtd, см. код на этом сайте: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#no-op-entityresolver