Пример проверки XML-файла по схеме XSD v1.1 в Java 1.8

  • Моя текущая проверка не работает для схем XSD v1.1. Я пробовал много вещей, чтобы изменить это, но до сих пор безуспешно.
  • Для меня не имеет значения, выполняется ли решение с помощью Saxon или Xerces (Редактировать: я не хочу тратить деньги на решение проблемы, и похоже, что проверка Saxon XSD1.1 не бесплатна, поэтому я должен придерживаться Ксерсес)
  • Да, я уже искал SO для этого, но пока ни один из фрагментов кода не помог мне получить рабочую проверку.
  • Код будет использоваться в плагине eclipse, если это имеет значение.
  • Я добавил следующий jar-файл в проект/путь к классам, однако похоже, что он не используется в моем коде:
<dependency>
  <groupId>xerces</groupId>
  <artifactId>xercesImpl</artifactId>
  <version>2.11.0</version>
</dependency>

Вот код, который я использовал до сих пор для проверки (нет проблем с его сбросом, если его нельзя использовать для xsd1.1):

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;

import org.apache.xerces.parsers.DOMParser;
import org.apache.xerces.xni.parser.XMLInputSource;

....

public List<MyError> validate(File xmlFile) {
    List<MyError> errors = null;
    try {
        DOMParser parser = new DOMParser();
        parser.setFeature(XmlUtils.VALIDATION, true);
        parser.setFeature(XmlUtils.VALIDATION_SCHEMA, true);
        parser.setFeature(XmlUtils.ALL_SCHEMA_LOCATIONS, true);
        parser.setFeature(XmlUtils.DEFER_NODE_EXPANSION, false);

        Handler handler = new Handler(xmlFile, parser);
        parser.setErrorHandler(handler);

        // there probably are smarter ways to do this
        String uri = xmlFile.toURI().toString().replace("%20", " ");
        InputStream inputStream = new FileInputStream(xmlFile);
        XMLInputSource inputSource = new XMLInputSource("", uri, uri, inputStream, "UTF-8");
        parser.parse(inputSource);

        errors = handler.getErrors();

    }
    catch (Exception e)
    {
        ConsoleHandler.printError("Document " + xmlFile.getName() + " has not been parsed correctly: " + e.getMessage(), true);
        ConsoleHandler.printStackTrace(e);
    }
    // printing the errors happens in some other method
    return errors;
}

person Alex    schedule 11.03.2016    source источник


Ответы (2)


Вы пометили это «саксонским», поэтому я предполагаю, что вы ищете саксонское решение. (Но вы также пометили его «Xerces»). Вы явно создали экземпляр Xerces DOMParser, поэтому здесь нет ничего, что могло бы вызвать Saxon в качестве средства проверки схемы. Если вам нужно решение Xerces, то я не эксперт и не могу вам помочь. Если вам нужно решение Saxon, вы найдете множество примеров в файле загрузки saxon-resources (доступном как на SourceForge, так и на saxonica.com). Вот несколько выдержек, которые делают примерно то, что вы хотите:

пример s9api:

            Processor proc = new Processor(true);
            SchemaManager sm = proc.getSchemaManager();
            sm.load(new StreamSource(new File("data/books.xsd")));

            try {
                SchemaValidator sv = sm.newSchemaValidator();
                sv.validate(new StreamSource(new File("data/books.xml")));
                System.out.println("First schema validation succeeded (as planned)");
            } catch (SaxonApiException err) {
                System.out.println("First schema validation failed");
            }

Пример JAXP:

            System.setProperty("javax.xml.transform.TransformerFactory",
                               "com.saxonica.config.EnterpriseTransformerFactory");
            TransformerFactory factory = TransformerFactory.newInstance();
            System.err.println("TransformerFactory class: " + factory.getClass().getName());
            factory.setAttribute(FeatureKeys.SCHEMA_VALIDATION, new Integer(Validation.STRICT));
            factory.setAttribute(FeatureKeys.VALIDATION_WARNINGS, Boolean.TRUE);
            if (args.length > 1) {
                StreamSource schema = new StreamSource(new File(args[1]).toURI().toString());
                ((EnterpriseTransformerFactory)factory).addSchema(schema);
            }
            Transformer trans = factory.newTransformer();
            StreamSource source = new StreamSource(new File(args[0]).toURI().toString());
            SAXResult sink = new SAXResult(new DefaultHandler());
            trans.transform(source, sink);
person Michael Kay    schedule 11.03.2016
comment
Спасибо за ответ! Саксонское решение мне подходит, мне не нужно придерживаться Xerces. Я испытаю это, как только у меня будет время. Для завершения (не стесняйтесь добавлять): Примеры, например. можно найти здесь: saxonica.com/html /документация/схема-обработка/ - person Alex; 14.03.2016
comment
Похоже, что валидатора Saxon XSD1.1 в свободном доступе нет: Saxon-EE (корпоративная версия) является полнофункциональным коммерческим продуктом. Saxon-EE 9.7 предлагает ... А также полностью совместимый процессор схемы XSD 1.0 и XSD 1.1 и .... Поскольку я не хочу тратить деньги на валидатор XSD1.1 (добавлено в сообщение № 1), я думаю Я не могу использовать Saxon, верно? - person Alex; 14.03.2016
comment
Да, верно, валидатор схемы Saxon обойдется вам в 90 фунтов стерлингов для первого пользователя и 60 фунтов стерлингов для последующих пользователей. - person Michael Kay; 14.03.2016

Хорошо, я наконец-то получил свой XML для проверки по схеме XSD1.1 с помощью Xerces. Вот зависимость, которую я использовал:

<dependency>
    <groupId>org.opengis.cite.xerces</groupId>
    <artifactId>xercesImpl-xsd11</artifactId>
    <version>2.12-beta-r1667115</version>
</dependency>

(Похоже, что официальной версии xerces, поддерживающей xsd1.1, пока нет. Что меня сначала смутило: Xercex v2.11.0, похоже, не поддерживает XSD1.1, а 2.11.0.beta поддерживает)

И вот исходный код, который я использовал:

import java.io.File;
import java.io.IOException;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.xml.sax.SAXException;

public class MyClass {

    public static void main(String[] args) {

        try {
            validateFile(new File("Test.xml") , new  File("Test.xsd"));
        } catch (Exception e) {

            e.printStackTrace();
        }
    }

    private static void validateFile(File xmlFile, File xsdFile) throws SAXException, IOException
    {
        SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1");
        File schemaLocation = xsdFile;
        Schema schema = factory.newSchema(schemaLocation);
        Validator validator = schema.newValidator();
        Source source = new StreamSource(xmlFile);
        try
        {
            validator.validate(source);
            System.out.println(xmlFile.getName() + " is valid.");
        }
        catch (SAXException ex)
        {
            System.out.println(xmlFile.getName() + " is not valid because ");
            System.out.println(ex.getMessage());
        }
    }
}

Изменить: однако мой код еще не работает как плагин eclipse. Когда проверка запускается в плагине, я получаю следующую ошибку:

!ENTRY org.eclipse.core.jobs 4 2 2016-03-15 15:14:37.852
!MESSAGE An internal error occurred during: "validation job".
!STACK 0
javax.xml.validation.SchemaFactoryConfigurationError: Provider for class javax.xml.validation.SchemaFactory cannot be created
    at javax.xml.validation.SchemaFactoryFinder.findServiceProvider(SchemaFactoryFinder.java:414)
    at javax.xml.validation.SchemaFactoryFinder._newFactory(SchemaFactoryFinder.java:218)
    at javax.xml.validation.SchemaFactoryFinder.newFactory(SchemaFactoryFinder.java:145)
    at javax.xml.validation.SchemaFactory.newInstance(SchemaFactory.java:213)
    at plugin.control.validation.MyValidator.validateFile(MyValidator.java:39)
    at
...

Строка моего кода, где выдается исключение:

SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1");
person Alex    schedule 14.03.2016