How to validate against schema in JAXB 2.0 without marshalling?

前端 未结 3 1360
时光说笑
时光说笑 2020-11-30 20:11

I need to validate my JAXB objects before marshalling to an XML file. Prior to JAXB 2.0, one could use a javax.xml.bind.Validator. But that has been deprecated so I\'m try

相关标签:
3条回答
  • 2020-11-30 20:43

    Firstly, javax.xml.bind.Validator has been deprecated in favour of javax.xml.validation.Schema (javadoc). The idea is that you parse your schema via a javax.xml.validation.SchemaFactory (javadoc), and inject that into the marshaller/unmarshaller.

    As for your question regarding validation without marshalling, the problem here is that JAXB actually delegates the validation to Xerces (or whichever SAX processor you're using), and Xerces validates your document as a stream of SAX events. So in order to validate, you need to perform some kind of marshalling.

    The lowest-impact implementation of this would be to use a "/dev/null" implementation of a SAX processor. Marshalling to a null OutputStream would still involve XML generation, which is wasteful. So I would suggest:

    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 will discard all the events, and the marshal() operation will throw a JAXBException if validation against the schema fails.

    0 讨论(0)
  • 2020-11-30 20:54

    You could use a javax.xml.bind.util.JAXBSource (javadoc) and a javax.xml.validation.Validator (javadoc), throw in an implementation of org.xml.sax.ErrorHandler (javadoc) and do the following:

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

    For More Information, See My Blog

    • http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html
    0 讨论(0)
  • 2020-11-30 21:10

    This how we did it. I had to find a way to validate the xml file versus an xsd corresponding to the version of the xml since we have many apps using different versions of the xml content.

    I didn't really find any good examples on the net and finally finished with this. Hope this will help.

    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);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题