unmarshal parse jaxbunmarshaller ejemplo java jaxb

jaxbunmarshaller - parse xml java jaxb



¿Cómo validar contra el esquema en JAXB 2.0 sin ordenar? (3)

Necesito validar mis objetos JAXB antes de convertirlos en un archivo XML. Antes de JAXB 2.0, uno podría usar un javax.xml.bind.Validator. Pero eso ha quedado en desuso, así que estoy tratando de descubrir la forma correcta de hacerlo. Estoy familiarizado con la validación en tiempo de marshall pero en mi caso solo quiero saber si es válido. Supongo que podría ir a un archivo temporal o memoria y tirarlo, pero me pregunto si hay una solución más elegante.


Así lo hicimos. Tuve que encontrar una manera de validar el archivo xml frente a un xsd correspondiente a la versión del xml, ya que tenemos muchas aplicaciones que utilizan diferentes versiones del contenido xml.

Realmente no encontré ningún buen ejemplo en la red y finalmente terminé con esto. Espero que esto ayude.

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); } } }


Puede usar un javax.xml.bind.util.JAXBSource ( javadoc ) y un javax.xml.validation.Validator ( javadoc ), lanzar una implementación de org.xml.sax.ErrorHandler ( javadoc ) y hacer lo siguiente:

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); } }

Para más información, vea mi blog.


En primer lugar, javax.xml.bind.Validator ha quedado en desuso en favor de javax.xml.validation.Schema ( javadoc ). La idea es que usted analice su esquema a través de un javax.xml.validation.SchemaFactory ( javadoc ), e inyecte eso en el marshaller / unmarshaller.

En cuanto a su pregunta sobre la validación sin clasificación, el problema aquí es que JAXB en realidad delega la validación a Xerces (o al procesador SAX que esté usando), y Xerces valida su documento como una secuencia de eventos de SAX. Entonces, para validar, necesitas realizar algún tipo de ordenamiento.

La implementación de menor impacto de esto sería utilizar una implementación "/ dev / null" de un procesador SAX. La reducción a un OutputStream nulo todavía implicaría la generación de XML, que es un desperdicio. Así que sugiero:

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 descartará todos los eventos, y la operación marshal() lanzará una excepción JAXBException si la validación contra el esquema falla.