Проверка по схеме с помощью JAXB - PullRequest
12 голосов
/ 22 марта 2010

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

У меня есть XML-схема, которую я использовал с xjc для созданиямой JAXB обязательный.Это хорошо работает, когда XML правильно сформирован.К сожалению, он также не жалуется, когда XML не очень хорошо сформирован.Я не могу понять, как правильно выполнить полную проверку схемы, когда пытаюсь разобрать файл XML.

Мне удалось использовать ValidationEventCollector для обработки событий, что работает для ошибок синтаксического анализа XML, таких как несоответствующие теги, ноне вызывает никаких событий, когда есть тег, который требуется, но полностью отсутствует.

Из того, что я видел, проверка может быть выполнена снова в схеме, но вы должны знать путь к схеме, чтобы пройтиэто в метод setSchema ().У меня проблема в том, что путь к схеме хранится в заголовке XML, и я не могу знать, во время выполнения, где схема будет.Вот почему он хранится в XML-файле:

<?xml version="1.0" encoding="utf-8"?>
<DDSSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="/a/big/long/path/to/a/schema/file/DDSSettings.xsd">
<Field1>1</Field1>
<Field2>-1</Field2>

... и т. Д.

Каждый пример, который я вижу, использует setValidating (true), который сейчас устарел, поэтому выдает исключение.

Это код Java, который у меня есть, который, кажется, выполняет только проверку XML, а не проверку схемы:

try {
    JAXBContext jc = new JAXBContext() {
        private final JAXBContext jaxbContext = JAXBContext.newInstance("blah");

        @Override
        public Unmarshaller createUnmarshaller() throws JAXBException {
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            ValidationEventCollector vec = new ValidationEventCollector() {
                @Override
                public boolean handleEvent(ValidationEvent event) throws RuntimeException {
                    ValidationEventLocator vel = event.getLocator();
                    if (event.getSeverity() == event.ERROR || event.getSeverity() == event.FATAL_ERROR) {
                        String error = "XML Validation Exception:  " + event.getMessage() + " at row: " + vel.getLineNumber() + " column: " + vel.getColumnNumber();
                        System.out.println(error);
                    }
                    m_unmarshallingOk = false;
                    return false;
                }
            };
            unmarshaller.setEventHandler(vec);

            return unmarshaller;
        }

        @Override
        public Marshaller createMarshaller() throws JAXBException {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        @SuppressWarnings("deprecation")
        public Validator createValidator() throws JAXBException {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    };

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    m_ddsSettings = (com.ultra.DDSSettings)unmarshaller.unmarshal(new File(xmlfileName));
} catch (UnmarshalException ex) {
    Logger.getLogger(UniversalDomainParticipant.class.getName()).log(
    Level.SEVERE,
    null, ex);
} catch (JAXBException ex) {
    Logger.getLogger(UniversalDomainParticipant.class.getName()).log(
    Level.SEVERE,
    null, ex);
}

Так каков правильный способ проверки?Я ожидал, что в сгенерированных JAXB классах будет метод validate (), но я думаю, это было бы слишком просто для Java.

Ответы [ 2 ]

15 голосов
/ 22 марта 2010

ОК, я нашел решение. Использование фабрики схем для создания схемы, но без указания файла схемы, заставляет его работать с noNamespaceSchemaLocation, указанным в файле XML.

Таким образом, код сверху добавил это:

SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setSchema(schema);
m_ddsSettings = (com.ultra.DDSSettings)unmarshaller.unmarshal(new File(xmlfileName));

Позор, который потратил лучшую часть 24 часов, чтобы найти ответ!

Javadoc для SchemaFactory.newSchema() говорит:

Для схемы XML этот метод создает Объект схемы, который выполняет проверку используя подсказки местоположения, указанные в документы.

Возвращенный объект схемы предполагает что если документы ссылаются на то же URL в схеме расположения подсказок, они всегда будет разрешать одну и ту же схему документ. Это суждение позволяет реализации для повторного использования разобранного результаты документов схемы так, чтобы несколько проверок против одного и того же схема будет работать быстрее.

1 голос
/ 22 марта 2010

Насколько я знаю, вам просто нужно установить схему с помощью Marshaller.setSchema () для схемы, созданной SchemaFactory из вашего DDSSettings.xsd. Это включит проверку.

...