Как проверить XML-документ, используя схему RELAX NG и JAXP?

Я хотел бы проверить документы XML, используя схемы RELAX NG, и я хотел бы использовать API проверки JAXP.

Из Googling оказалось, что я могу использовать Jing и ISO RELAX JARV to JAXP Bridge. К сожалению, после добавления обоих в мой classpath я не могу заставить его работать. SchemaFactory просто бросает IllegalArgumentException как только он пытается создать экземпляр фабрики - я заглянул внутрь SchemaFactory, по-видимому SchemaFactoryFinder возвращает нулевой результат.

Поэтому я был бы признателен за ответы на любой вопрос:

  • Как я могу заставить это работать с Цзином и этим мостом?
  • Есть ли лучший / другой набор библиотек, которые я должен попробовать?

Мне это нужно для работы с Java 5 и Java 6.

Спасибо!

5 ответов

Решение

См. Блог Штефана Бодевига, написанный 7 марта 2008 года, под названием RELAX NG Validation в XMLUnit:

Со вчерашнего вечера ствол XMLUnit содержит новый класс Validator, основанный на javax.xml.validation, который является частью JAXP 1.3 (то есть Java5 +).

...

Насколько мне известно, не существует реализации JAXP, которая бы поддерживала RELAX NG из коробки. Собственный JAXP 1.4 от Sun (Java6+), безусловно, этого не делает. Некоторые поиски привели меня в блог Kohsuke Kawaguchi, который должен знать, учитывая его работу над JAXP, Multi Schema Validator от Sun, изорелакс и другие вещи.

Использование его isorelax-bridge и Jing никуда не привело меня на Java6. Я вернулся к статье Kohsuke Kawaguchi и прочитал комментарии: мост не работает с Java6, так как они изменили алгоритм поиска SchemaFactory. Хорошо, попробовал Java5 вместо этого - прогресс, теперь я получаю исключение NullPointerException где-то внутри Jing, поэтому, по крайней мере, он загружает фабрику. Затем я заменил Jing на MSV (который сейчас здесь, независимо от того, сколько ссылок ведет вас на страницу стека WebServices в Sun, особенно для "хороших URL-адресов никогда не меняются"), и на самом деле мои упрощенные тесты проходят.

Поэтому вам, возможно, придется прыгнуть через несколько обручей, чтобы получить поддержку RELAX NG в вашей настройке JAXP - в моем случае сработал мост Java5, MSV и Kawaguchi, но комментарии показывают, что он должен быть выполним и с Java6 - но как только вам удастся настроить все правильно, XMLUnit теперь будет там, чтобы позволить вам подтвердить правильность вашего документа в модульных тестах. Кажется, что он не работает для компактного синтаксиса, хотя.

Чтобы прочитать комментарии к блогу Кохсуке Кавагути, вы должны использовать archive.org, потому что теперь они как-то пропали:

Java 5 интерпретирует файл поставщика услуг как список пар ключ / значение, что является нарушением спецификации JAR-файла Java 5 & 6, но соответствует вашему примеру.

Java 6 анализирует файл поставщика услуг, как указано, т.е. в виде списка полностью определенных имен классов, но не может создать экземпляр SchemaFactory вашего адаптера, поскольку содержимое файла поставщика услуг недопустимо.

Чтобы быть совместимым с Java 5 и Java 6 без необходимости изменения файла JAR JAXP-JARV-адаптера, можно просто добавить другой файл JAR, содержащий правильный файл поставщика услуг javax.xml.validation.SchemaFactory.

Я исправил эту ошибку в Java 1.6 с помощью следующей строки:

// Specify you want a factory for RELAX NG "compact"
System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI, "com.thaiopensource.relaxng.jaxp.CompactSyntaxSchemaFactory");

SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);

Это позволяет мне использовать Jing для проверки XML-документа по схеме Compact RELAX NG. Полный пример ниже. Я не использовал мост или что-нибудь еще. У пути к классу времени выполнения есть только jing.jar (20091111) и мой собственный класс Validator.

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

import javax.xml.XMLConstants;
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 Validate
{

    public static void main(String[] args) throws SAXException, IOException
    {
        // Specify you want a factory for RELAX NG
        System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI, "com.thaiopensource.relaxng.jaxp.CompactSyntaxSchemaFactory");
        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);

        // Load the specific schema you want.
        // Here I load it from a java.io.File, but we could also use a
        // java.net.URL or a javax.xml.transform.Source
        File schemaLocation = new File(args[0]);

        // Compile the schema.
        Schema schema = factory.newSchema(schemaLocation);

        // Get a validator from the schema.
        Validator validator = schema.newValidator();

        for (int i = 1; i < args.length; i++)
        {
            String file = args[i];

            // Check the document
            try
            {
                validator.validate(new StreamSource(new File(file)));
                System.out.println(file + " is valid.");
            }
            catch (SAXException ex)
            {
                System.out.print(file + " is not valid because: " + ex.getMessage());
            }
        }
    }

}

Еще раз, я только что протестировал этот ион Java 1.6.

$ java -version
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)

Я не могу помочь вам с API проверки JAXP, но Nux предоставляет класс, который может проверять практически все типы схем, известных человеку. Что касается схем RELAX NG, используйте этот фабричный метод для создания соответствующего объекта валидатора.

Другим вариантом является Trang, переводчик RelaxNG-to-XMLSchema. Я полагаю, что он предназначен для использования в качестве инструмента сборки, а не библиотеки времени выполнения, но лучшим вариантом может быть преобразование вашей схемы в XMLSchema с использованием Trang во время сборки, а затем проверка этого. Таким образом, вы сможете точно увидеть, как выглядит перевод, и в то же время получите полное преимущество поддержки JAXP в XML-схемах.

... IllegalArgumentException, как только он пытается создать фабрику

Означает, что язык схемы не распознается, может быть несколько причин.

  • Поскольку Sun JDK по умолчанию не включает валидатор RELAX NG, возможно, он не найден.
  • Возможно, вы допустили ошибку в идентификаторе языка схемы.
Другие вопросы по тегам