我正在使用XSD来验证JAXB中XML的特定部分,但由于XML命名空间而失败,您能建议吗?提前谢谢。
错误是“cvc-elt.1:找不到元素的声明'c:MessageDtl'”
XSD
的 parent.xsd 的
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
targetNamespace="ns.parent"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:c="ns.child"
xmlns="ns.parent">
<xs:import schemaLocation="child.xsd" namespace="ns.child"></xs:import>
<xs:complexType name="MessageType">
<xs:sequence>
<xs:element name="Message" type="c:Document"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="Message" type="MessageType"></xs:element>
</xs:schema>
的 child.xsd 的
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns="ns.child"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="ns.child"
elementFormDefault="qualified">
<xs:element name="Document" type="Document"/>
<xs:complexType name="Document">
<xs:sequence>
<xs:element name="MessageDtl" type="MessageDtl"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="MessageDtl">
<xs:sequence>
<xs:element name="field1" type="xs:string"/>
<xs:element name="field2" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Message xmlns="ns.parent"
xmlns:c="ns.child"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="ns.parent parent.xsd ns.child child.xsd">
<Message>
<c:MessageDtl>
<c:field1>field 1</c:field1>
<c:field2>field 2</c:field2>
</c:MessageDtl>
</Message>
</Message>
示例代码
public class TestXmlValidator {
public static void main(String[] args) throws Exception {
SchemaFactory SCHEMA_FACTORY = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = SCHEMA_FACTORY.newSchema(new File("D:/researches/xmlvalidation/xsd/parent.xsd"));
JAXBContext jaxbContext = JAXBContext.newInstance("com.test");
SAXSource saxSource = new SAXSource(new InputSource(new FileInputStream("d:/researches/xmlvalidation/sample.xml")));
InputFactoryImpl XML_INPUT_FACTORY; //fastxml
XML_INPUT_FACTORY = new com.fasterxml.aalto.stax.InputFactoryImpl();
XML_INPUT_FACTORY.setProperty(XML_INPUT_FACTORY.IS_NAMESPACE_AWARE, Boolean.TRUE);
XML_INPUT_FACTORY.setProperty(XML_INPUT_FACTORY.IS_VALIDATING, Boolean.TRUE);
XML_INPUT_FACTORY.configureForSpeed();
XMLEventReader2 xmlEventReader = (XMLEventReader2) XML_INPUT_FACTORY.createXMLEventReader(saxSource);
XMLEvent event;
while ((event = xmlEventReader.peek()) != null) {
if(event.isStartElement()){
System.out.println("=====> " + event.asStartElement().getName().getLocalPart());
if("MessageDtl".equals(event.asStartElement().getName().getLocalPart())){
break;
}
}
xmlEventReader.nextEvent();
}
ParseValidationExceptionHandler validationHandler = new ParseValidationExceptionHandler();
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
jaxbUnmarshaller.setEventHandler(validationHandler);
jaxbUnmarshaller.setSchema(schema);
JAXBElement<MessageDtl> result = jaxbUnmarshaller.unmarshal(xmlEventReader, MessageDtl.class);
if(validationHandler.getEvents() != null && validationHandler.getEvents().length>0){
for(ValidationEvent e : validationHandler.getEvents()){
System.out.println("=====> " + e.getMessage());
}
}
xmlEventReader.close();
System.out.println("Completed.");
}
}
class ParseValidationExceptionHandler implements ValidationEventHandler {
private final List<ValidationEvent> events = new ArrayList<ValidationEvent>();
public ValidationEvent[] getEvents() {
return events.toArray(new ValidationEvent[events.size()]);
}
public boolean handleEvent( ValidationEvent event ) {
events.add(event);
return true;
}
}
但是,如果我们尝试验证整个XML,那就是成功。以下是示例代码。
public class TestXmlValidator {
public static void main(String[] args) throws Exception {
SchemaFactory SCHEMA_FACTORY = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = SCHEMA_FACTORY.newSchema(new File("D:/researches/xmlvalidation/xsd/parent.xsd"));
Validator validator = schema.newValidator();
SAXSource saxSource = new SAXSource(new InputSource(new FileInputStream("d:/researches/xmlvalidation/sample.xml")));
validator.validate(saxSource);
System.out.println("Completed.");
}
}
答案 0 :(得分:0)
由于您已在Schema
上指定了Unmarshaller
的实例,因此将在启用架构验证的情况下完成解组操作(请参阅:http://blog.bdoughan.com/2010/12/jaxb-and-marshalunmarshal-schema.html)。
jaxbUnmarshaller.setSchema(schema);
JAXBElement<MessageDtl> result = jaxbUnmarshaller.unmarshal(xmlEventReader, MessageDtl.class);
即使您已将XMLEventReader
推进到c:MessageDetail
这是一个嵌套元素,但JAXB会在启动解组时将其视为根元素。验证发生在unmarshal中,因此首先要做的是在XML模式中查找名为MessageDetail
的根元素,因为这不存在,验证将失败。
<强>解决方案强>
MessageDetail
是一个全局元素。XMLEventReader