Comment valider par rapport au schéma dans JAXB 2.0 sans marshalling?

Je dois valider mes objets JAXB avant de les regrouper dans un fichier XML. Avant JAXB 2.0, on pouvait utiliser un javax.XML.lier.Validateurs. 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 marshall à un fichier temporaire ou de la mémoire et le jeter mais se demandant s'il y a une solution plus élégante.

46
demandé sur skaffman 2009-10-13 17:57:20

3 réponses

Tout d'Abord, javax.xml.bind.Validator, a été déprécié en faveur de javax.xml.validation.Schema (javadoc). L'idée est que vous analysez votre schéma via un javax.xml.validation.SchemaFactory (javadoc), et injecter cela dans le marshaller / unmarshaller.

En ce qui concerne votre question concernant la validation sans marshalling, le problème ici est que JAXB délègue réellement la validation à Xerces (ou quel que soit le processeur SAX que vous utilisez), et Xerces valide votre document en tant que flux d'événements SAX. Donc, afin de les valider, vous avez besoin de effectuer certains type de regroupement.

L'implémentation la plus faible de ceci serait d'utiliser une implémentation "/ dev / null " d'un processeur SAX. Le Marshalling vers un OutputStream null impliquerait toujours la génération 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 supprimera tous les événements et l'opération marshal() lancera une exception JAXBException si la validation par rapport au schéma échoue.

71
répondu skaffman 2017-09-08 09:37:07

Vous pouvez utiliser un javax.xml.bind.util.JAXBSource (javadoc) et un javax.xml.validation.Validator (javadoc), de lancer la mise en œuvre de org.xml.sax.ErrorHandler (javadoc) et procédez de la manière suivante:

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

}

Pour Plus D'Informations, Voir Mon Blog

11
répondu Blaise Doughan 2017-09-08 10:57:21

C'est comme ça que nous l'avons fait. J'ai dû trouver un moyen de valider le fichier xml par rapport à un xsd correspondant à la version du xml depuis, nous avons de nombreuses applications en utilisant différentes versions du contenu xml.

Je n'ai pas vraiment trouvé de bons exemples sur le net et j'ai finalement fini avec ça. Espérons 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 {
    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);
        }
    }
}
4
répondu Pat B 2017-08-09 03:38:22