Информация о DTD и связанные с ней ошибки при проверке (XSD-схема) Можно ли их игнорировать?

Итак, у меня есть большое количество файлов XML. В течение многих лет они вызывали проблемы, потому что люди, которые их писали, делали их вручную, поэтому ошибки, естественно, возникали. Пришло время проверить их и предоставить обратную связь о том, что не так при попытке использовать эти XML-файлы.

Я использую парсер SAX и получаю список ошибок.

Ниже мой код

  BookValidationErrorHandler errorHandler = new BookValidationErrorHandler();

        SAXParserFactory factory = SAXParserFactory.newInstance();
        factory.setValidating(true);
        factory.setNamespaceAware(true);

        SchemaFactory schemaFactory = 
            SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");

        factory.setSchema(schemaFactory.newSchema(
            new Source[] {new StreamSource("test.xsd")}));


        javax.xml.parsers.SAXParser parser = factory.newSAXParser();
        org.xml.sax.XMLReader reader = parser.getXMLReader();

        reader.setErrorHandler(errorHandler);
        reader.parse(new InputSource("bad.xml"));

Первая пара ошибок всегда:

Номер строки: 2: документ недействителен: грамматика не найдена. Номер строки: 2: корневой элемент документа "credits", должен соответствовать корневому элементу DOCTYPE "null".

Мы не можем пойти и отредактировать эти тысячи XML-файлов, которые необходимо проверить.

Есть ли что-нибудь, что я могу легко добавить в начало источника, чтобы предотвратить это? Есть ли способ сказать синтаксическому анализатору игнорировать эти ошибки, связанные с DTD? Даже не уверен, что имеется в виду под грамматикой. Я примерно понимаю, что означает второе.


person bobber205    schedule 04.03.2011    source источник


Ответы (3)


Параметр setValidating(true) запрашивает проверку DTD и вызывает ошибку, если DTD не существует. Если вам нужна только проверка схемы, а не проверка DTD, используйте setValidating(false). Из Javadoc для setValidating() :

Чтобы использовать современные языки схем, такие как W3C XML Schema или RELAX NG, вместо DTD, вы можете настроить свой синтаксический анализатор как непроверяющий синтаксический анализатор, оставив метод setValidating(boolean) ложным, а затем использовать метод setSchema(Schema) для связывания схемы с синтаксическим анализатором.

person Michael Kay    schedule 04.03.2011

на этих возвышениях у меня была та же проблема; Я нашел эту тему в поисках решения. Мое решение состояло в том, чтобы использовать EntityResolver. Кажется, что установить схему недостаточно... по крайней мере, для меня. Это пример EntityResolver:

public class CustomResolver implements EntityResolver {
    @Override
    public InputSource resolveEntity(String publicId, String systemId) 
            throws SAXException, IOException {

        if (systemId.equals("http://namespace1.example.com/ex1")) {
            return new InputSource("xsd_for_namespace1_path"));
        } else if (systemId.equals("http://namespace2.example.com/ex2")) {
            return new InputSource("xsd_for_namespace2_path"));
        } else if (systemId.equals("http://namespace3.example.com/ex3")) {
            return new InputSource("xsd_for_namespace3_path")); 
        }

        return null;
    }
}

Я также отключаю свойство setValidating(). Это моя конфигурация парсера:

SAXParserFactory saxpf = SAXParserFactory.newInstance();
saxpf.setNamespaceAware(true);
saxpf.setSchema(getSchema());
saxpf.setValidating(false);
SAXParser saxParser = saxpf.newSAXParser();
saxParser.getParser().setEntityResolver(new XSDResolver());

Метод getSchema() создает экземпляр схемы, как вы это делаете в своем коде, но с большим количеством источников.

Я надеюсь, что это может помочь, кто нашел ту же ошибку.

person Leo    schedule 20.04.2011
comment
Я забыл одну вещь! Если xml имеет путь schemaLocaltion=Namespace, EntityResolver не нужен в процессе проверки; у меня работает тот же код без настройки преобразователя. У меня такое чувство, что setSchema бесполезна, но я отказываюсь это принимать. - person Leo; 20.04.2011

Вы по-прежнему можете использовать проверяющий синтаксический анализатор, и вам не нужно заранее задавать схему в синтаксическом анализаторе, если вы используете JAXP-совместимый синтаксический анализатор и правильно его настроили согласно документации Oracle:

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(true);
SAXParser saxParser = spf.newSAXParser();
// Important step next:  Tell the parser which XML schema-definition language to expect:
saxParser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
// Now when we parse a file without a DTD, we no longer get an error 
// (as long as an XSD schema is defined in the file):
saxParser.parse(source, handler);
person daiscog    schedule 21.01.2015