Comment valider contre un schéma dans JAXB 2.0 sans marshalling?

Je dois valider mes objects JAXB avant de les classer dans un fichier XML. Avant JAXB 2.0, on pouvait utiliser un javax.xml.bind.Validator. Mais cela a été déprécié, alors j’essaie de trouver la bonne façon de le faire. Je suis familier avec la validation au moment de marshall mais dans mon cas je veux juste savoir si c’est valide. Je suppose que je pourrais rassembler un fichier temporaire ou une mémoire et le jeter, mais je me demandais s’il existe une solution plus élégante.

Tout d’abord, javax.xml.bind.Validator est devenu obsolète en faveur de javax.xml.validation.Schema ( javadoc ). L’idée est que vous parsingz votre schéma via un javax.xml.validation.SchemaFactory ( javadoc ), et injectez cela dans le marshaller / unmarshaller.

En ce qui concerne votre question concernant la validation sans regroupement, le problème est que JAXB délègue effectivement la validation à Xerces (ou à tout processeur SAX que vous utilisez), et Xerces valide votre document en tant que stream d’événements SAX. Donc, pour valider, vous devez effectuer une sorte de formation.

L’implémentation à l’impact le plus faible serait d’utiliser une implémentation “/ dev / null” d’un processeur SAX. Le regroupement en un stream de sortie nul impliquerait toujours la génération de XML, ce qui est inutile. Donc, je suggère:

 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 tous les événements et l’opération marshal() lancera une exception JAXBException si la validation contre le schéma échoue.

Vous pouvez utiliser un javax.xml.bind.util.JAXBSource ( javadoc ) et un javax.xml.validation.Validator ( javadoc ), lancer une implémentation de org.xml.sax.ErrorHandler ( javadoc ) et procéder comme suit:

 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(Ssortingng[] 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); } } 

Pour plus d’informations, voir mon blog

C’est comme ça qu’on l’a fait. J’ai dû trouver un moyen de valider le fichier XML par rapport à un fichier xsd correspondant à la version du fichier XML, car nous avons de nombreuses applications utilisant des versions différentes du contenu XML.

Je n’ai pas vraiment trouvé de bons exemples sur le net et j’ai finalement fini avec ça. J’espère que cela aidera.

 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 { SsortingngReader reader = new SsortingngReader(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(); Ssortingng 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); } } }