Как читать хорошо сформированный XML в Java, но пропустить схему?
Я хочу прочитать XML файл, в котором есть объявление схемы.
И все, что я хочу сделать, прочитайте. Мне все равно, действительно ли это, но я хочу, чтобы он был хорошо сформирован.
Проблема заключается в том, что читатель пытается прочитать файл схемы и не работает.
Я не хочу, чтобы он даже пытался.
Я попытался отключить проверку, но он все еще настаивает на попытке прочитать файл схемы.
В идеале я бы хотел сделать это с помощью запаса Java 5 JDK.
Вот что я до сих пор очень прост:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(file);
и здесь исключение я возвращаюсь:
java.lang.RuntimeException: java.io.IOException: Server returned HTTP response code: 503 for URL: http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
Да, этот HAPPENS является схемой XHTML, но это не проблема "XHTML", это проблема XML. Просто указывая, что так люди не отвлекаются. И в этом случае W3C в основном говорит: "Не просите об этом, это глупая идея", и я согласен. Но, опять же, это деталь вопроса, а не корень этого. Я не хочу просить об этом ВСЕ.
Ответы
Ответ 1
Ссылка не для Схемы, а для DTD.
Файлы DTD могут содержать не только структурные правила. Они также могут содержать ссылки на сущности. Анализаторы XML обязаны загружать и анализировать ссылки DTD, поскольку они могут содержать ссылки на сущности, которые могут влиять на то, как анализируется документ, и содержимое файла (вы могли бы иметь ссылку на объект для символов или даже целые фразы текста).
Если вы хотите избежать загрузки и анализа DTD с ссылкой, вы можете предоставить свой собственный EntityResolver и протестировать DTD с ссылкой и решить, загружать ли локальную копию файла DTD или просто вернуть null.
Пример кода из ответного ответа на пользовательский EntityResolvers:
builder.setEntityResolver(new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
if (systemId.contains("foo.dtd")) {
return new InputSource(new StringReader(""));
} else {
return null;
}
}
});
Ответ 2
Самый простой ответ - это однострочный, вызываемый после создания DocumentBuilderFactory:
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
Бесстыдно вырезано из Сделать DocumentBuilder.parse игнорировать ссылки DTD.
Ответ 3
Проблема здесь не в проверке. Независимо от настроек проверки, анализатор все равно попытается разрешить любые ссылки в вашем документе, такие как сущности, DTD и (иногда) схемы. Только после этого он решает проверить их использование (или нет). Вам нужно подключить средство распознавания сущности для "перехвата" этих попыток при де-привязке.
Откажитесь от Apache XML Resolver для легкого (ish) способа сделать это.
Ответ 4
Я не тестировал это, но вы можете попробовать вызвать setSchema на factory, передав null.
то есть.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
dbf.setSchema(null);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(file);
Обновление: смотря на DocumentBuilderImpl, похоже, что это может сработать, из конструктора он проверит грамматику из factory перед проверкой схемы.
Из DocumentBuilderFactoryImpl:
public void setSchema(Schema grammar) {
this.grammar = grammar;
}
В конструкторе DocumentBuilderImpl:
...
this.grammar = dbf.getSchema();
if (grammar != null) {
XMLParserConfiguration config = domParser.getXMLParserConfiguration();
XMLComponent validatorComponent = null;
/** For Xerces grammars, use built-in schema validator. **/
...
}
Ответ 5
Это хорошо работает для проверки правильности формирования xml независимо от того, содержит ли он объявление DTD или нет.