Как читать хорошо сформированный 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;
            }
        }
    });

Ответ 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 или нет.