Tuesday, June 3, 2014

JAXB Marshalling and Unmarshalling

Suppose your XSD file is your.xsd in a directory schemas.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://..."
 targetNamespace="http://..."
 elementFormDefault="qualified" attributeFormDefault="unqualified"
 version="2.0">

 <xs:element name="foo" type="Xyz" />
 <xs:complexType name="Xyz">
  <xs:sequence>
   ...
  </xs:sequence>
 </xs:complexType>
</xs:schema>
In maven, you can use the following to generate the java classes from the xsd file in the build process.
<plugin>
 <groupId>org.jvnet.jaxb2.maven2</groupId>
 <artifactId>maven-jaxb2-plugin</artifactId>
 <version>0.7.3</version>
 <executions>
  <execution>
   <phase>generate-sources</phase>
   <goals>
    <goal>generate</goal>
   </goals>
  </execution>
 </executions>
 <configuration>
  <generatePackage>your.package</generatePackage>
  <schemaDirectory>path.of.folder.of.xsd</schemaDirectory>
 </configuration>
</plugin>

To marshal a java object to XML, and validate

Note that depending on whether an element is defined as a root element or not, the marshal/unmarshal code can be different. The following code is for the XSD defined above.

 public String marshall(Xyz fooObj) throws JAXBException,
   SAXException {
  JAXBElement xmlMsg = new your.dir.ObjectFactory()
    .createXyz(fooObj);
  JAXBContext jaxbContext = JAXBContext.newInstance(Xyz.class);
  Marshaller marshaller = jaxbContext.createMarshaller();

  // valiate that the data in the object conforms to the schema
  SchemaFactory schemaFactory = SchemaFactory
    .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
  URL xsdUrl = getClass().getClassLoader().getResource(
    "schemas/your.xsd"); // schemas/your.xsd needs to be in the classpath
  Schema schema = schemaFactory.newSchema(xsdUrl);
  marshaller.setSchema(schema); // this enables the validation

  StringWriter sw = new StringWriter();
  marshaller.marshal(xmlMsg, sw);
  return sw.toString();
}

To unmarshal from XML to a java object

JAXBContext jaxbContext = JAXBContext
  .newInstance(your.dir.ObjectFactory.class);

Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
String msg = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><foo xmlns=...>...</foo>";
  
StringReader reader = new StringReader(msg);

// validate if the message conforms to the schema
SchemaFactory schemaFactory = SchemaFactory
    .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
URL xsdUrl = getClass().getClassLoader().getResource(
    "schemas/your.xsd"); // schemas/your.xsd needs to be in the classpath
Schema schema = schemaFactory.newSchema(xsdUrl);
jaxbUnmarshaller.setSchema(schema);  // this enables the validation

JAXBElement elem = (JAXBElement) jaxbUnmarshaller.unmarshal(reader);

Xyz fooObj = (Xyz) elem.getValue();