51 votes

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

Je dois valider mes objets JAXB avant de les transférer dans un fichier XML. Avant JAXB 2.0, on pouvait utiliser un fichier javax.xml.bind.Validator. Mais cela a été déconseillé et j'essaie de trouver la bonne façon de procéder. Je suis habitué à valider au marshall mais dans mon cas, je veux juste savoir si sa validité. Je suppose que je pourrais rassembler un fichier temporaire ou une mémoire et le jeter tout en me demandant s'il existe une solution plus élégante.

79voto

skaffman Points 197885

Tout d'abord, javax.xml.bind.Validator a été dépréciée en faveur de l' javax.xml.validation.Schema. L'idée est que vous analysez votre schéma, et de les injecter dans le marshaller/unmarshaller.

Quant à votre question concernant la validation sans triage, le problème ici est que JAXB réalité des délégués de la validation de Xerces (ou n'importe quel SAX processeur que vous utilisez), et Xerces valide votre document sous forme d'un flux d'événements SAX. Donc pour valider, vous devez effectuer certains type de regroupement.

Le plus faible impact de la mise en œuvre de ce qui serait d'utiliser un "/dev/null" la mise en œuvre d'un SAX processeur. Le regroupement pour un null OutputStream nécessiterait quand même génération XML, ce qui est un gaspillage. Donc, je vous 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' marshal() opération de jeter un JAXBException si la validation par rapport au schéma d'échec.

13voto

Blaise Doughan Points 75613

Vous pouvez utiliser un javax.xml.bind.util.JAXBSource et un javax.xml.validation.Validator et procédez 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(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

5voto

Pat B Points 775

C'est comme ça qu'on l'a fait. Je devais trouver un moyen de valider le fichier XML par rapport à un xsd correspondant à la version du XML, car de nombreuses applications utilisent 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. 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 {

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

    }
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X