Necesito validar mis objetos JAXB antes de ordenar a un archivo XML. Antes de JAXB 2.0, se podía usar un javax.xml.bind.Validator. Pero eso ha sido obsoleto, así que estoy tratando de encontrar la forma adecuada de hacerlo. Estoy familiarizado con la validación en tiempo de Marshall, pero en mi caso solo quiero saber si es válida. Supongo que podría utilizar un archivo o memoria temporal y tirarlo, pero me pregunto si hay una solución más elegante.¿Cómo validar contra esquema en JAXB 2.0 sin clasificación?
Respuesta
En primer lugar, javax.xml.bind.Validator
ha quedado obsoleto a favor de javax.xml.validation.Schema
(javadoc). La idea es que analice su esquema a través de 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 realmente delega la validación a Xerces (o el procesador SAX que esté utilizando) y Xerces valida su documento como una secuencia de eventos SAX. Por lo tanto, para validar, debe realizar algún tipo de clasificación de.
La implementación de menor impacto de esto sería usar una implementación "/ dev/null" de un procesador SAX. La alineación con un OutputStream nulo aún implicaría la generación de XML, lo cual es un desperdicio. Así que yo sugeriría:
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()
a tirar un JAXBException si la validación con el esquema de falla.
Así lo hicimos. Tenía 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 usan versiones diferentes 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);
}
}
}
Se puede usar un javax.xml.bind.util.JAXBSource
(javadoc) y un javax.xml.validation.Validator
(javadoc), el tiro en 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, véase mi Blog
- 1. ¿Se puede validar XML estructurado con JAXB 2.0?
- 2. Validar xml creado usando jaxb contra un archivo xsd
- 3. ¿Cómo validar big xml contra el esquema xsd?
- 4. Usando .NET para validar XML contra un esquema
- 5. ¿Puedo validar una expresión XPath contra un esquema XML?
- 6. Validar mensaje SOAP contra WSDL
- 7. ¿Por qué JAXB no quiere validar
- 8. ¿Validar un esquema XSD?
- 9. ¿Cómo validar un archivo xml contra un esquema XSD utilizando la biblioteca de Amara en Python?
- 10. ¿Cómo puedo validar una cadena JSON contra un esquema mediante programación?
- 11. Cómo escribir un test de unidad para JAXB 2.0 Marshalling
- 12. cómo comparar/validar el esquema sql
- 13. ¿Cómo validar un ticket Kerberos contra un servidor en Java?
- 14. error al validar el esquema XML
- 15. Cómo validar xml contra un archivo DTD en Python
- 16. ¿Cómo puedo validar documentos contra esquemas Schematron en Java?
- 17. Generando clases jaxb desde un esquema
- 18. ¿JAXB admite valores de esquema predeterminados?
- 19. LinkageError JAXB 2.0 -> 2.1 (Tomcat)
- 20. Error al validar XML contra XSD
- 21. JAXP: cómo validar un org.w3c.dom.Document en un esquema XML
- 22. Validar cadena contra USPS abreviaturas Estado
- 23. Validar XML contra el software XSD
- 24. Validar XML contra XSD en un único método
- 25. ¿Validar múltiples propiedades de esquema de Mongoose?
- 26. Jaxb DateTime sin timezone
- 27. JBoss RESTeasy JAX-RS JAXB validación de esquema con Decorator
- 28. ¿Cómo validar xml contra xsd y obtener errores * ALL *?
- 29. ¿Cómo generar Java Enum desde el esquema XML con JAXB?
- 30. puede validar xsd contra xml en vs 2010?
Un problema con este enfoque: no se obtiene información del número de línea/número de columna sobre los errores de validación con este método, por lo que es difícil rastrear problemas. –
¿Es ese el enfoque aplicable para Desmarcar? No puedo crear el objeto JAXBSource. – Xelian