如何在没有编组的情况下对JAXB 2.0中的模式进行validation?

我需要在封送到XML文件之前validation我的JAXB对象。 在JAXB 2.0之前,可以使用javax.xml.bind.Validator。 但是,这已被弃用,所以我想弄清楚这样做的正确方法。 我熟悉在马歇尔时间validation,但在我的情况下,我只是想知道它是否有效。 我想我可以马歇尔临时文件或内存扔掉,但想知道是否有一个更优雅的解决scheme。

首先, javax.xml.bind.Validator已被弃用,以支持javax.xml.validation.Schema ( javadoc )。 这个想法是,你通过一个javax.xml.validation.SchemaFactory ( javadoc )来parsing你的模式,并将其注入到编组/解组器(marshaller / unmarshaller)中。

至于你关于无编组validation的问题,这里的问题是JAXB实际上将validation委托给Xerces(或者你正在使用的SAX处理器),Xercesvalidation你的文档是SAX事件stream。 所以为了validation,你需要执行某种编组。

影响最小的实现是使用SAX处理器的“/ dev / null”实现。 编组为空OutputStream仍然涉及XML生成,这是浪费。 所以我会build议:

 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(locationOfMySchema); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setSchema(schema); marshaller.marshal(objectToMarshal, new DefaultHandler()); 

DefaultHandler将放弃所有事件,如果对模式进行validation失败, marshal()操作将抛出JAXBException。

您可以使用javax.xml.bind.util.JAXBSource ( javadoc )和javax.xml.validation.Validator ( javadoc ), org.xml.sax.ErrorHandler ( javadoc )的实现并执行以下操作:

 import java.io.File; import javax.xml.XMLConstants; import javax.xml.bind.JAXBContext; import javax.xml.bind.util.JAXBSource; import javax.xml.validation.*; public class Demo { public static void main(String[] args) throws Exception { Customer customer = new Customer(); customer.setName("Jane Doe"); customer.getPhoneNumbers().add(new PhoneNumber()); customer.getPhoneNumbers().add(new PhoneNumber()); customer.getPhoneNumbers().add(new PhoneNumber()); JAXBContext jc = JAXBContext.newInstance(Customer.class); JAXBSource source = new JAXBSource(jc, customer); SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = sf.newSchema(new File("customer.xsd")); Validator validator = schema.newValidator(); validator.setErrorHandler(new MyErrorHandler()); validator.validate(source); } } 

有关更多信息,请参阅我的博客

这是我们如何做到的。 我必须find一种方法来validationxml文件与xml版本对应的xsd,因为我们有许多应用程序使用不同版本的xml内容。

我没有在网上find任何好的例子,终于完成了。 希望这会有所帮助。

 ValidationEventCollector vec = new ValidationEventCollector(); SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); URL xsdURL = getClass().getResource("/xsd/" + xsd); Schema schema = sf.newSchema(xsdURL); //You should change your jaxbContext here for your stuff.... Unmarshaller um = (getJAXBContext(NotificationReponseEnum.NOTIFICATION, notificationWrapper.getEnteteNotification().getTypeNotification())) .createUnmarshaller(); um.setSchema(schema); try { StringReader reader = new StringReader(xml); um.setEventHandler(vec); um.unmarshal(reader); } catch (javax.xml.bind.UnmarshalException ex) { if (vec != null && vec.hasEvents()) { erreurs = new ArrayList < MessageErreur > (); for (ValidationEvent ve: vec.getEvents()) { MessageErreur erreur = new MessageErreur(); String msg = ve.getMessage(); ValidationEventLocator vel = ve.getLocator(); int numLigne = vel.getLineNumber(); int numColonne = vel.getColumnNumber(); erreur.setMessage(msg); msgErreur.setCode(ve.getSeverity()) erreur.setException(ve.getLinkedException()); erreur.setPosition(numLigne, numColonne); erreurs.add(erreur); logger.debug("Erreur de validation xml" + "erreur : " + numLigne + "." + numColonne + ": " + msg); } } }