JAXB Without an XML Schema

Have you ever received an XML Sample without a Schema that you wanted to use with JAXB or some other XML Binding? It actually happens more than I would like. The common thing to do is simply not to use any XML Binding at all. This is not ideal since JAXB is so much easier to use than DOM. Yes there are better Java libraries out there to deal with XML (or Groovy) but that is not the topic of discussion here.

You can always try to write your own schema from the sample provided but that can take some time to do. Many times by the time you are done, you could have just used something else. Another option is to generate a schema for you.

Let us consider the following scenario. You have been provided the following XML sample.


<?xml version="1.0" encoding="UTF-8"?>
<people>
    <Person id="123">
        <name>Chris Dail</name>
        <phone>555-1111</phone>
    </Person>
</people>

The first thing you need to do to use JAXB is to get a schema for this XML. There is a free software tool called the Trang Converter that can be used to convert between schema types. It has a cool feature that can generate a schema from an XML sample file. This is what I am going to do here.

The XML editor I use is called Oxygen XML. It actually has the Trang Converter built in as an option. Going to Tools->Schema Converter gives you a UI on top of the Trang Converter.

Using this, you take the sample and generate a schema for it. After the convert, you end up with a schema looking something like this:


<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="people">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="Person"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="Person">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="name"/>
        <xs:element ref="phone"/>
      </xs:sequence>
      <xs:attribute name="id" use="required" type="xs:integer"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="name" type="xs:string"/>
  <xs:element name="phone" type="xs:NMTOKEN"/>
</xs:schema>

You can then use JAXB to generate your object model from this using the following command:


"%JAVA_HOME%\bin\xjc" -p com.chrisdail.jaxb.sample *.xsd

The result looks like this:


parsing a schema...
compiling a schema...
com\chrisdail\jaxb\sample\ObjectFactory.java
com\chrisdail\jaxb\sample\People.java
com\chrisdail\jaxb\sample\Person.java

Now you have a JAXB generated object model from just an XML sample file.

Example of the generate Person.java class.


//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2010.08.30 at 12:31:56 PM ADT 
//


package com.chrisdail.jaxb.sample;

import java.math.BigInteger;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;


/**
 * <p>Java class for anonymous complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element ref="{}name"/>
 *         &lt;element ref="{}phone"/>
 *       &lt;/sequence>
 *       &lt;attribute name="id" use="required" type="{http://www.w3.org/2001/XMLSchema}integer" />
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "name",
    "phone"
})
@XmlRootElement(name = "Person")
public class Person {

    @XmlElement(required = true)
    protected String name;
    @XmlElement(required = true)
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    @XmlSchemaType(name = "NMTOKEN")
    protected String phone;
    @XmlAttribute(required = true)
    protected BigInteger id;

    /**
     * Gets the value of the name property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the value of the name property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setName(String value) {
        this.name = value;
    }

    /**
     * Gets the value of the phone property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getPhone() {
        return phone;
    }

    /**
     * Sets the value of the phone property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setPhone(String value) {
        this.phone = value;
    }

    /**
     * Gets the value of the id property.
     * 
     * @return
     *     possible object is
     *     {@link BigInteger }
     *     
     */
    public BigInteger getId() {
        return id;
    }

    /**
     * Sets the value of the id property.
     * 
     * @param value
     *     allowed object is
     *     {@link BigInteger }
     *     
     */
    public void setId(BigInteger value) {
        this.id = value;
    }

}