[英]Jaxb2Marshaller schema validation doesn't seem to be working
我經歷過Jaxb2Marshaller在進行解組時無法驗證我對XSD的無效XML。 我正在使用Spring 4.0.0.RELEASE和Java 7。
這是一個例子:
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>
我使用Spring Tool Suite從這個XSD生成了JAXB POJO到com.testraptor.xml.jaxb
包。
我的XML文件無效 : invalid.xml
<?xml version="1.0" encoding="UTF-8"?>
<fruit>
<banana quantity="5" />
<apple quantity="3" />
</fruit>
如你所見,我打破了架構,因為在水果標簽中有一個選擇,我同時使用了香蕉和蘋果。
我的Spring配置文件: app-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 ...
正如您所看到的,當Unmarshaller可以驗證時,Jaxb2Marshaller忘記驗證我的無效XML文件。
任何人都可以告訴我我的代碼可能有什么問題嗎?
在運行時配置Jaxb2Marshaller
時遇到了同樣的問題。 通過Spring XML設置模式的建議解決方案讓我想到:我的代碼設置屬性和Spring之間的區別是什么?
答案很簡單: Jaxb2Marshaller
實現了org.springframework.beans.factory.InitializingBean
,它定義了生命周期方法afterPropertiesSet()
並且在設置了屬性后,Springs BeanFactory
調用了此方法。
因此,解決方案是在使用setSchema()
設置架構屬性之后調用afterPropertiesSet()
。 因為在該方法中,schema屬性( 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...
嘗試通過調用setValidationEventHandler()來設置validationEventHandler並查看它是否已被調用?
setValidationEventHandler(new ValidationEventHandler() {
@Override
public boolean handleEvent(ValidationEvent event) {
System.out.println(event.getLinkedException().getMessage());
return false;
}
});)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.