XSD 使用架构问题进行验证
XSD Validation Using Schema Issue
我有一个 xml 文件,例如
<root>
<requestId>1</requestId>
<subRequest>
<id>11</id>
<date>18-02-2015</date>
</subRequest>
<subRequest>
<id>12</id>
<date>19-02-2015</date>
</subRequest>
.
.
</root>
我有一个 XSD 文件,我无法更改该文件中的日期必须采用某种格式。 "subRequest"标签可以有1000个条目。我创建了一个模式验证来检查格式。
所以我的问题出在这 1000 个条目中,如果只有 2 个条目的日期格式不正确,我怎么知道这 2 个条目的 ID。
我在使用 JAXB(unmarshaller) 将此 xml 转换为 bean 时正在检查此内容。我使用了模式验证,并且 validator.getLocalizedMessage() 为对象和节点都提供了 null。我只能看到 lineNumber 和有关问题格式的一般消息。
您可以执行以下操作:
Unmarshaller.Listener
您可以创建一个 Unmarshaller.Listener
来跟踪当前正在解组的 SubRequest
。
import javax.xml.bind.Unmarshaller;
public class SubRequestListener extends Unmarshaller.Listener {
private SubRequest subRequest;
@Override
public void beforeUnmarshal(Object target, Object parent) {
if(target.getClass() == SubRequest.class) {
subRequest = (SubRequest) target;
} else {
subRequest = null;
}
}
public SubRequest getSubRequest() {
return subRequest;
}
}
XmlAdapter
然后执行 XmlAdapter
来验证 Date
属性 的内容。在此示例中,我假设您将其存储为 String
。如果您将其存储为其他内容(即 Date
),则将 XmlAdapter<String, String>
更改为 XmlAdapter<Date, String>
。此 XmlAdapter
引用 Unmarshaller.Listener
以获取 SubRequest
.
的实例
import java.text.SimpleDateFormat;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class DateValidator extends XmlAdapter<String, String> {
private SubRequestListener subRequestListener;
public DateValidator() {
this.subRequestListener = new SubRequestListener();
}
public DateValidator(SubRequestListener subRequestListener) {
this.subRequestListener = subRequestListener;
}
@Override
public String marshal(String value) throws Exception {
return value;
}
@Override
public String unmarshal(String value) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
sdf.applyPattern(value);
} catch(IllegalArgumentException e) {
SubRequest subRequest = subRequestListener.getSubRequest();
System.out.println(subRequest.getId());
}
return value;
}
}
子请求
以下是您如何引用 XmlAdapter
。
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlAccessorType(XmlAccessType.FIELD)
public class SubRequest {
private int id;
@XmlJavaTypeAdapter(DateValidator.class)
private String date;
public int getId() {
return id;
}
}
演示
下面是一些关于如何设置的演示代码。
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
SubRequestListener unmarshallerListener = new SubRequestListener();
unmarshaller.setListener(unmarshallerListener);
DateValidator dateAdapter = new DateValidator(unmarshallerListener);
unmarshaller.setAdapter(dateAdapter);
File xml = new File("input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
我知道您正在寻找基于 JAXB 的解决方案。
但是,如果您只想找到那个特定的错误,您也可以使用简单的 SAXParser
来快速找到它。也许它可以帮助您首先找到导致错误的原因。
编辑
我在 DefaultHandler
中添加了一个字段,允许您获取引发错误的子请求 ID。
正如我所说,这应该有助于追查错误,它并没有赢得美丽奖。
import java.io.File;
import java.io.IOException;
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
public class RequestParser {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
Schema schema = null;
try {
String language = XMLConstants.W3C_XML_SCHEMA_NS_URI;
SchemaFactory factory = SchemaFactory.newInstance(language);
schema = factory.newSchema(new File("YOUR_SCHEMA.xsd"));
} catch (Exception e) {
e.printStackTrace();
}
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setSchema(schema);
SAXParser parser = spf.newSAXParser();
parser.parse(new File("YOUR_DOCUMENT.xml"), new DefaultHandler(){
String currentNodeQName = "";
String currentSubrequestId = "";
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
currentNodeQName = qName;
}
public void characters(char[] ch, int start, int length) throws SAXException {
if (currentNodeQName.equals("id")) {
currentSubrequestId = new String(ch, start, length);
}
}
public void warning(SAXParseException e) throws SAXException {
System.out.println("Warning in subrequest with id " + currentSubrequestId);
e.printStackTrace();
}
public void error(SAXParseException e) throws SAXException {
System.out.println("Error in subrequest with id: " + currentSubrequestId);
e.printStackTrace();
}
public void fatalError(SAXParseException e) throws SAXException {
System.out.println("Fatal error in subrequest with id " + currentSubrequestId);
e.printStackTrace();
}
});
}
}
您还可以在这三个异常块处设置断点,这将为您提供有关手头错误的更多信息。
编辑 2
示例输出:
Error in subrequest with id 12
org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: '19-02-2015' is not a valid value for 'date'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:423)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3188)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3103)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3013)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2156)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:824)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1789)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2950)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:513)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:815)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:744)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:128)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1208)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:543)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:331)
at so28836220.RequestParser.main(RequestParser.java:43)
您可以执行以下操作:
Unmarshaller.Listener & ValidationEventHandler
您可以为这个用例创建 Unmarshaller.Listener
和 ValidationEventHandler
的组合。
import javax.xml.bind.*;
public class SubRequestValidator extends Unmarshaller.Listener implements ValidationEventHandler {
private SubRequest subRequest;
@Override
public void beforeUnmarshal(Object target, Object parent) {
if(target.getClass() == SubRequest.class) {
subRequest = (SubRequest) target;
} else {
subRequest = null;
}
}
public SubRequest getSubRequest() {
return subRequest;
}
@Override
public boolean handleEvent(ValidationEvent validationEvent) {
if(subRequest != null) {
System.out.println(subRequest.getId());
System.out.println(validationEvent.getMessage());
}
return validationEvent.getSeverity() != ValidationEvent.FATAL_ERROR;
}
}
那么除了 Schema
.
的实例之外,您还可以在 Unmarshaller
上设置两者
SubRequestValidator subRequestValidator = new SubRequestValidator();
unmarshaller.setListener(subRequestValidator);
unmarshaller.setEventHandler(subRequestValidator);
演示代码
下面是一些支持material完成的例子:
XML 架构 (schema.xsd)
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="root">
<complexType>
<sequence>
<element name="requestId" type="int"/>
<element name="subRequest" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="id" type="int"/>
<element name="date" type="date"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
XML (input.xml)
<root>
<requestId>1</requestId>
<subRequest>
<id>11</id>
<date>2015-02-18</date>
</subRequest>
<subRequest>
<id>12</id>
<date>WRONG</date>
</subRequest>
<subRequest>
<id>13</id>
<date>2015-02-19</date>
</subRequest>
</root>
根目录
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private int requestId;
@XmlElement(name="subRequest")
private List<SubRequest> subRequests;
}
子请求
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class SubRequest {
private int id;
private String date;
public int getId() {
return id;
}
}
演示
import java.io.File;
import javax.xml.XMLConstants;
import javax.xml.bind.*;
import javax.xml.validation.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File("src/forum28584265/schema.xsd"));
unmarshaller.setSchema(schema);
SubRequestValidator subRequestValidator = new SubRequestValidator();
unmarshaller.setListener(subRequestValidator);
unmarshaller.setEventHandler(subRequestValidator);
File xml = new File("src/forum28584265/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
}
}
输出
12
cvc-datatype-valid.1.2.1: 'WRONG' is not a valid value for 'date'.
Exception in thread "main" javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'WRONG' is not a valid value for 'date'.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:514)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:215)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:184)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:142)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:151)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:169)
at forum28584265.Demo.main(Demo.java:23)
Caused by: org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'WRONG' is not a valid value for 'date'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:423)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3188)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3103)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3013)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2156)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:824)
at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.endElement(ValidatorHandlerImpl.java:566)
at com.sun.xml.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.endElement(ValidatingUnmarshaller.java:101)
at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:156)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:604)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1789)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2950)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:513)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:815)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:744)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:128)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1208)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:543)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:211)
... 6 more
我有一个 xml 文件,例如
<root>
<requestId>1</requestId>
<subRequest>
<id>11</id>
<date>18-02-2015</date>
</subRequest>
<subRequest>
<id>12</id>
<date>19-02-2015</date>
</subRequest>
.
.
</root>
我有一个 XSD 文件,我无法更改该文件中的日期必须采用某种格式。 "subRequest"标签可以有1000个条目。我创建了一个模式验证来检查格式。
所以我的问题出在这 1000 个条目中,如果只有 2 个条目的日期格式不正确,我怎么知道这 2 个条目的 ID。
我在使用 JAXB(unmarshaller) 将此 xml 转换为 bean 时正在检查此内容。我使用了模式验证,并且 validator.getLocalizedMessage() 为对象和节点都提供了 null。我只能看到 lineNumber 和有关问题格式的一般消息。
您可以执行以下操作:
Unmarshaller.Listener
您可以创建一个 Unmarshaller.Listener
来跟踪当前正在解组的 SubRequest
。
import javax.xml.bind.Unmarshaller;
public class SubRequestListener extends Unmarshaller.Listener {
private SubRequest subRequest;
@Override
public void beforeUnmarshal(Object target, Object parent) {
if(target.getClass() == SubRequest.class) {
subRequest = (SubRequest) target;
} else {
subRequest = null;
}
}
public SubRequest getSubRequest() {
return subRequest;
}
}
XmlAdapter
然后执行 XmlAdapter
来验证 Date
属性 的内容。在此示例中,我假设您将其存储为 String
。如果您将其存储为其他内容(即 Date
),则将 XmlAdapter<String, String>
更改为 XmlAdapter<Date, String>
。此 XmlAdapter
引用 Unmarshaller.Listener
以获取 SubRequest
.
import java.text.SimpleDateFormat;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class DateValidator extends XmlAdapter<String, String> {
private SubRequestListener subRequestListener;
public DateValidator() {
this.subRequestListener = new SubRequestListener();
}
public DateValidator(SubRequestListener subRequestListener) {
this.subRequestListener = subRequestListener;
}
@Override
public String marshal(String value) throws Exception {
return value;
}
@Override
public String unmarshal(String value) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
sdf.applyPattern(value);
} catch(IllegalArgumentException e) {
SubRequest subRequest = subRequestListener.getSubRequest();
System.out.println(subRequest.getId());
}
return value;
}
}
子请求
以下是您如何引用 XmlAdapter
。
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlAccessorType(XmlAccessType.FIELD)
public class SubRequest {
private int id;
@XmlJavaTypeAdapter(DateValidator.class)
private String date;
public int getId() {
return id;
}
}
演示
下面是一些关于如何设置的演示代码。
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
SubRequestListener unmarshallerListener = new SubRequestListener();
unmarshaller.setListener(unmarshallerListener);
DateValidator dateAdapter = new DateValidator(unmarshallerListener);
unmarshaller.setAdapter(dateAdapter);
File xml = new File("input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
我知道您正在寻找基于 JAXB 的解决方案。
但是,如果您只想找到那个特定的错误,您也可以使用简单的 SAXParser
来快速找到它。也许它可以帮助您首先找到导致错误的原因。
编辑
我在 DefaultHandler
中添加了一个字段,允许您获取引发错误的子请求 ID。
正如我所说,这应该有助于追查错误,它并没有赢得美丽奖。
import java.io.File;
import java.io.IOException;
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
public class RequestParser {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
Schema schema = null;
try {
String language = XMLConstants.W3C_XML_SCHEMA_NS_URI;
SchemaFactory factory = SchemaFactory.newInstance(language);
schema = factory.newSchema(new File("YOUR_SCHEMA.xsd"));
} catch (Exception e) {
e.printStackTrace();
}
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setSchema(schema);
SAXParser parser = spf.newSAXParser();
parser.parse(new File("YOUR_DOCUMENT.xml"), new DefaultHandler(){
String currentNodeQName = "";
String currentSubrequestId = "";
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
currentNodeQName = qName;
}
public void characters(char[] ch, int start, int length) throws SAXException {
if (currentNodeQName.equals("id")) {
currentSubrequestId = new String(ch, start, length);
}
}
public void warning(SAXParseException e) throws SAXException {
System.out.println("Warning in subrequest with id " + currentSubrequestId);
e.printStackTrace();
}
public void error(SAXParseException e) throws SAXException {
System.out.println("Error in subrequest with id: " + currentSubrequestId);
e.printStackTrace();
}
public void fatalError(SAXParseException e) throws SAXException {
System.out.println("Fatal error in subrequest with id " + currentSubrequestId);
e.printStackTrace();
}
});
}
}
您还可以在这三个异常块处设置断点,这将为您提供有关手头错误的更多信息。
编辑 2
示例输出:
Error in subrequest with id 12
org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: '19-02-2015' is not a valid value for 'date'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:423)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3188)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3103)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3013)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2156)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:824)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1789)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2950)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:513)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:815)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:744)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:128)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1208)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:543)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:331)
at so28836220.RequestParser.main(RequestParser.java:43)
您可以执行以下操作:
Unmarshaller.Listener & ValidationEventHandler
您可以为这个用例创建 Unmarshaller.Listener
和 ValidationEventHandler
的组合。
import javax.xml.bind.*;
public class SubRequestValidator extends Unmarshaller.Listener implements ValidationEventHandler {
private SubRequest subRequest;
@Override
public void beforeUnmarshal(Object target, Object parent) {
if(target.getClass() == SubRequest.class) {
subRequest = (SubRequest) target;
} else {
subRequest = null;
}
}
public SubRequest getSubRequest() {
return subRequest;
}
@Override
public boolean handleEvent(ValidationEvent validationEvent) {
if(subRequest != null) {
System.out.println(subRequest.getId());
System.out.println(validationEvent.getMessage());
}
return validationEvent.getSeverity() != ValidationEvent.FATAL_ERROR;
}
}
那么除了 Schema
.
Unmarshaller
上设置两者
SubRequestValidator subRequestValidator = new SubRequestValidator();
unmarshaller.setListener(subRequestValidator);
unmarshaller.setEventHandler(subRequestValidator);
演示代码
下面是一些支持material完成的例子:
XML 架构 (schema.xsd)
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="root">
<complexType>
<sequence>
<element name="requestId" type="int"/>
<element name="subRequest" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="id" type="int"/>
<element name="date" type="date"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
XML (input.xml)
<root>
<requestId>1</requestId>
<subRequest>
<id>11</id>
<date>2015-02-18</date>
</subRequest>
<subRequest>
<id>12</id>
<date>WRONG</date>
</subRequest>
<subRequest>
<id>13</id>
<date>2015-02-19</date>
</subRequest>
</root>
根目录
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private int requestId;
@XmlElement(name="subRequest")
private List<SubRequest> subRequests;
}
子请求
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class SubRequest {
private int id;
private String date;
public int getId() {
return id;
}
}
演示
import java.io.File;
import javax.xml.XMLConstants;
import javax.xml.bind.*;
import javax.xml.validation.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File("src/forum28584265/schema.xsd"));
unmarshaller.setSchema(schema);
SubRequestValidator subRequestValidator = new SubRequestValidator();
unmarshaller.setListener(subRequestValidator);
unmarshaller.setEventHandler(subRequestValidator);
File xml = new File("src/forum28584265/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
}
}
输出
12
cvc-datatype-valid.1.2.1: 'WRONG' is not a valid value for 'date'.
Exception in thread "main" javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'WRONG' is not a valid value for 'date'.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:514)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:215)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:184)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:142)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:151)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:169)
at forum28584265.Demo.main(Demo.java:23)
Caused by: org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'WRONG' is not a valid value for 'date'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:423)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3188)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3103)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3013)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2156)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:824)
at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.endElement(ValidatorHandlerImpl.java:566)
at com.sun.xml.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.endElement(ValidatingUnmarshaller.java:101)
at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:156)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:604)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1789)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2950)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:513)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:815)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:744)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:128)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1208)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:543)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:211)
... 6 more