Learn to validate XML against schema (xsd) and then unmarshalling XML to Java object. Also learn to check validation errors during xml schema validation if validation fails.
Read More: How to generate schema from JAXB classes
1. Convert XML to Java Object after XSD Validation
We have already seen the example to read XML file to Java object. Let’s modify that example to now validate the XML against XSD before populating the Employee
object.
package com.howtodoinjava.demo; import java.io.File; import javax.xml.XMLConstants; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.xml.sax.SAXException; import com.howtodoinjava.demo.model.Employee; public class JaxbExample { public static void main(String[] args) { String xmlFile = "employee.xml"; String xsdFile = "employee.xsd"; jaxbXmlFileToObject(xmlFile, xsdFile); } private static void jaxbXmlFileToObject(String xmlFile, String xsdFile) { JAXBContext jaxbContext; try { //Get JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class); //Create Unmarshaller Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); //Setup schema validator SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema employeeSchema = sf.newSchema(new File(xsdFile)); jaxbUnmarshaller.setSchema(employeeSchema); //Unmarshal xml file Employee employee = (Employee) jaxbUnmarshaller.unmarshal(new File(xmlFile)); System.out.println(employee); } catch (JAXBException | SAXException e) { e.printStackTrace(); } } }
Program output.
Employee [id=1, firstName=Lokesh, lastName=Gupta, department=Department [id=101, name=IT]]
Where the content of employee.xml
and employee.xsd
is given below.
<employees> <employee id="101"> <name>Lokesh Gupta</name> <title>Author</title> </employee> <employee id="102"> <name>Brian Lara</name> <title>Cricketer</title> </employee> </employees>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="department" type="department"/> <xs:element name="employee" type="employee"/> <xs:complexType name="employee"> <xs:sequence> <xs:element ref="department" minOccurs="0"/> <xs:element name="firstName" type="xs:string" minOccurs="0"/> <xs:element name="id" type="xs:int" minOccurs="0"/> <xs:element name="lastName" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="department"> <xs:sequence> <xs:element name="id" type="xs:int" minOccurs="0"/> <xs:element name="name" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> </xs:schema>
2. Schema Validation Errors
XSD validation against XML will not be always successful. Many times, you will get validation errors. These errors will be thrown as SAXException
. So catch this exception and it will have the context where validation failed.
e.g. I have update the schema file with this change.
<xs:element name="firstName" type="xs:string" minOccurs="0"/> //to <xs:element name="firstName" type="xs:int" minOccurs="0"/>
Now look at validation error.
javax.xml.bind.UnmarshalException - with linked exception: [org.xml.sax.SAXParseException; systemId: file:/C:/Users/lokesh/workspace/App/employee.xml; lineNumber: 7; columnNumber: 34; cvc-datatype-valid.1.2.1: 'Lokesh' is not a valid value for 'integer'.] at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:563) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:249) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189) at com.howtodoinjava.demo.JaxbExample.jaxbXmlFileToObject(JaxbExample.java:45) at com.howtodoinjava.demo.JaxbExample.main(JaxbExample.java:23) Caused by: org.xml.sax.SAXParseException; systemId: file:/C:/Users/lokesh/workspace/App/employee.xml; lineNumber: 7; columnNumber: 34; cvc-datatype-valid.1.2.1: 'Lokesh' is not a valid value for 'integer'. at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203) at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134) at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437) at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368) at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:458) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3237) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3152) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3062) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2140) at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:859) at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.endElement(ValidatorHandlerImpl.java:584) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.endElement(ValidatingUnmarshaller.java:91) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:165) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2973) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606) at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:649) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243) ... 7 more
Drop me your questions in comments section.
Happy Learning !!
Comments