2013-12-26 3 views
4

Я испытал, что Jaxb2Marshaller не смог проверить мой недопустимый XML на XSD, выполняя разметку. Я использую Spring 4.0.0.RELEASE и Java 7.Проверка правильности схемы Jaxb2Marshaller, похоже, не работает

Вот пример:

Файл XSD: fruit.xsd

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    elementFormDefault="qualified"> 

    <xs:attribute name="quantity" type="xs:string" /> 

    <xs:element name="fruit"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:choice> 
        <xs:element ref="banana" /> 
        <xs:element ref="apple" /> 
       </xs:choice> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 

    <xs:element name="banana"> 
     <xs:complexType> 
      <xs:attribute ref="quantity" use="required" /> 
     </xs:complexType> 
    </xs:element> 

    <xs:element name="apple"> 
     <xs:complexType> 
      <xs:attribute ref="quantity" use="required" /> 
     </xs:complexType> 
    </xs:element> 

</xs:schema> 

Я сгенерировал POJO, JAXB от этот XSD с пакетом Spring Tool Suite до com.testraptor.xml.jaxb.

Мой недопустимый XML-файл: invalid.xml

<?xml version="1.0" encoding="UTF-8"?> 
<fruit> 
    <banana quantity="5" /> 
    <apple quantity="3" /> 
</fruit> 

Как вы можете видеть, что я сломал схему, потому что есть выбор в фруктовой теге, и я использовал банан и яблоко в то же время.

Мой файл конфигурации Spring: приложение-config.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:oxm="http://www.springframework.org/schema/oxm" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
    http://www.springframework.org/schema/oxm 
    http://www.springframework.org/schema/oxm/spring-oxm-4.0.xsd"> 

    <oxm:jaxb2-marshaller id="marshaller" context-path="com.fruit.xml.jaxb" /> 

</beans> 

Основной класс для теста: Main.java

package com.fruit.test; 

import java.io.IOException; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.validation.Schema; 
import javax.xml.validation.SchemaFactory; 

import org.springframework.oxm.jaxb.Jaxb2Marshaller; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 
import org.springframework.core.io.Resource; 
import org.xml.sax.SAXException; 

import com.fruit.xml.jaxb.Fruit; 

public class Main { 

    public static void main(String[] args) { 
     ApplicationContext appContext = new ClassPathXmlApplicationContext(
       "app-context.xml"); 

     //--------------------------------SCHEMA VALIDATION IS OMITTED 

     Jaxb2Marshaller jaxb2Unmarshaller = (Jaxb2Marshaller) appContext 
       .getBean("marshaller"); 
     Resource schemaResource = appContext 
       .getResource("classpath:fruit.xsd"); 
     jaxb2Unmarshaller.setSchema(schemaResource); 

     Resource xml = appContext.getResource("classpath:invalid.xml"); 

     try { 
      Fruit fruit = (Fruit) jaxb2Unmarshaller.unmarshal(new StreamSource(xml.getInputStream())); 
      System.out.println("SCHEMA VALIDATION IS OMITTED:"); 
      System.out.println("Apple quantity is " + fruit.getApple().getQuantity()); 
      System.out.println("Banana quantity is " + fruit.getBanana().getQuantity()); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     //--------------------------------SCHEMA VALIDATION IS PASSED 
     SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI); 
     Schema schema; 
     try { 
      schema = sf.newSchema(schemaResource.getURL()); 
      JAXBContext context = JAXBContext.newInstance(Fruit.class); 
      Unmarshaller unmarshaller = (Unmarshaller) context.createUnmarshaller(); 
      unmarshaller.setSchema(schema); 
      Fruit fruit2 = (Fruit) unmarshaller.unmarshal(xml.getInputStream()); 
      System.out.println("SCHEMA VALIDATION IS PASSED:"); 
      System.out.println("Apple quantity is " + fruit2.getApple().getQuantity()); 
      System.out.println("Banana quantity is " + fruit2.getBanana().getQuantity()); 
     } catch (SAXException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (JAXBException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

} 

Когда я запускаю код я получаю следующее результат:

INFO: Loading XML bean definitions from class path resource [app-context.xml] 
dec. 26, 2013 9:33:22 DE org.springframework.oxm.jaxb.Jaxb2Marshaller createJaxbContextFromContextPath 
INFO: Creating JAXBContext with context path [com.fruit.xml.jaxb] 
SCHEMA VALIDATION IS OMITTED: 
Apple quantity is 3 
Banana quantity is 5 
javax.xml.bind.UnmarshalException 
- with linked exception: 
[org.xml.sax.SAXParseException; lineNumber: 4; columnNumber: 24; cvc-complex-type.2.4.d: Invalid content was found starting with element 'apple'. No child element is expected at this point.] 
    at ... 

Как вы можете видеть, Jaxb2Marshaller забыл проверить мой недопустимый XML-файл, в то время как Unmarshaller мог его проверить.

Может ли кто-нибудь дать мне понять, что может быть неправильным с моим кодом?

+0

ответ Тобиаса работал для меня. Если это сработает и для вас, можете ли вы пометить его как правильное решение? –

ответ

9

У меня была такая же проблема при настройке Jaxb2Marshaller во время выполнения. Предлагаемое решение по установке схемы через Spring XML заставило меня подумать: в чем разница между моим кодом, устанавливающим свойство и Spring?

Ответ прост: Jaxb2Marshaller реализует org.springframework.beans.factory.InitializingBean, который определяет метод жизненного цикла afterPropertiesSet() и этот метод вызывается после того, как Спрингс BeanFactory свойства были установлены.

Таким образом, решение должно называть afterPropertiesSet() после того, как setSchema() был использован для установки свойства схемы. Поскольку в этом методе свойство схемы (которое является массивом org.springframework.core.io.Resource), фактически используется для установки поля внутренней схемы типа javax.xml.validation.Schema, которое позднее используется для проверки схемы.

Пример:

Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); 
Resource schema = new ClassPathResource("fruit.xsd"); 
marshaller.setSchema(schema); 
marshaller.setContextPath("com.fruit.xml.jaxb"); 
// manually call Spring lifecycle method which actually loads the schema resource 
marshaller.afterPropertiesSet(); 
// use marshaller... 
+0

Спасибо! Я искал всюду, и это было единственное место, где я мог найти правильный ответ для точного контекста (проверка схемы с использованием Spring, Spring Jaxb2 marshaller и файла схемы) –

0

Попробуйте установить validationEventHandler, вызвав setValidationEventHandler() и посмотрим, вызвана ли его?

setValidationEventHandler(new ValidationEventHandler() { 
       @Override 
       public boolean handleEvent(ValidationEvent event) { 
        System.out.println(event.getLinkedException().getMessage()); 
        return false; 
       } 
      });) 
+0

Благодарим вас за ответ.Я попробовал это, но, к сожалению, добавление ValidationEventHandler не решило проблему, и кажется, что Jaxb2Marshaller забыл вызвать метод hanleEvent(), потому что я не могу увидеть его результат sysout на консоли. – atisss33

+0

Не уверен, что это поможет, но вы можете попробовать установить схему непосредственно в xml config <свойство name = "schema" value = "classpath: com/fruit/xml/jaxb/fruit.xsd" /> вместо jaxb2Unmarshaller.setSchema (schemaResource); – coder

+0

Элемент 'property' не может использоваться в определении oxm: jaxb2-marshaller bean, потому что я получил следующую ошибку: Неверный контент был найден, начиная с элемента 'property'. Ожидается одно из «{» http://www.springframework.org/schema/oxm":class-to-be-bound}. – atisss33

Смежные вопросы