Core Java

Using JAXB to generate XML from XSD

This is a post originally published by Mohamed Sanaulla from Experiences Unlimited, our latest JCG partner. Mohamed explains how to use JAXB to generate XML from a given XSD.

(NOTE: The original post has been slightly edited to improve readability)

We can use JAXB to marshal the Java objects into XML using the given Schema and vice versa- unmarshal XML into Java objects. The XML schema can be specified in DTD, XSD or other format.

The tool “xjc” can be used to generate the annotated Java classes from the XSD schema. One can download the Java Web Services Developer Pack (WSDP), it includes the JAXB implementation tools required. Here I will throw light on how to generate XML dynamically.

The sample XSD being used is:

– expense.xsd

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="expenseReport" type="ExpenseT" />
<xs:complexType name="ExpenseT">
    <xs:sequence>
        <xs:element name="user" type="UserT"/>
        <xs:element name="items" type="ItemListT"/>
    </xs:sequence>
</xs:complexType>
<xs:complexType name="UserT">
    <xs:sequence>
        <xs:element name="userName" type="xs:string" />
    </xs:sequence>
</xs:complexType>
<xs:complexType name="ItemListT">
     <xs:sequence>
         <xs:element name="item" type="ItemT" maxOccurs="unbounded"/>
     </xs:sequence>
</xs:complexType>
<xs:complexType name="ItemT">
     <xs:sequence>
         <xs:element name="itemName" type="xs:string" />
         <xs:element name="purchasedOn" type="xs:string" />
         <xs:element name="amount" type="xs:decimal" />
     </xs:sequence>
</xs:complexType>
</xs:schema>

Now we use the xjc tool to generate the corresponding Java classes. The generated Java classes are annotated appropriately. I am not going into details about the annotation of the classes, cause it would make things complicated.

xjc.exe expense.xsd

By default the command generates the Java classes in a directory named “generated”. There are lot of options which can be used with xjc and one can have a look at using

xjc -help

The below Main class uses the generated classes for creating the XML.

– Main.java

package generated;
 
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.math.BigDecimal;
 
public class Main
 
{
    public static void main(String[] args) throws JAXBException
    {
 
        ObjectFactory factory = new ObjectFactory();
 
        UserT user = factory.createUserT();
        user.setUserName("Sanaulla");
        ItemT item = factory.createItemT();
        item.setItemName("Seagate External HDD");
        item.setPurchasedOn("August 24, 2010");
        item.setAmount(new BigDecimal("6776.5"));
 
        ItemListT itemList = factory.createItemListT();
        itemList.getItem().add(item);
 
        ExpenseT expense = factory.createExpenseT();
        expense.setUser(user);
        expense.setItems(itemList);
 
        JAXBContext context = JAXBContext.newInstance("generated");
        JAXBElement<ExpenseT> element = factory.createExpenseReport(expense);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty("jaxb.formatted.output",Boolean.TRUE);
        marshaller.marshal(element,System.out);
    }
 
}

In the above XSD, we see that there are few complex types declared. These complex types generate in to Java classes. The child elements and attributes become the properties of the class and they are provided with getters and setters. One cannot directly create an instance of such classes, i.e. cannot call new on them. Whenever we compile a XSD, there is a ObjectFactory class generated – this is the factory for creating the instances of the XSD Complex types (Lines-17,19, 24, 27 in the above Java class).

Once we get the instance we populate the properties with corresponding data using the setters provided with the class. Also note that a complex element can have many complex elements as the members of the class. In that case we use the factory to get the instance of the complex elements and then use the setters of the outer complex element.

For example: In the above XSD, ExpenseT is a complex type which consists of UserT and a list of ItemT (ItemListT). In the above Java class – Lines 27,28,29 – we are creating an instance of ExpenseT and then using the setters to set the values of the UserT and ItemListT. The RootElement is created by calling createExpenseReport() for the factory. The name of the method is influenced by the name of the root element and the return type and the argument type of the method is same as that of the type of root element.

Once we have set the values for the different elements, attributes which are to go into the XML, its now time to actually generate the XML. We must have a Marshaller (to get XML from the Java objects) or an Unmarshaller (to get Java objects from XML).

We would need a Marshaller – which can be obtained from the JAXBContext instance. Lines 31,32 obtain an instance of Marshaller. Different properties can be set for the marshaller and in the above code we are setting the jaxb.formatted.output as true, which means that the XML obtained is neatly formatted making is readable to the user.

Different supported properties are:

  • jaxb.encoding
  • jaxb.formatted.output
  • jaxb.schemaLocation
  • jaxb.noNamespaceSchemaLocation
  • jaxb.fragment

<instance_of_marshaller>.marshal() is the method used to generate the XML. Its is overloaded to accept the following output mechanisms:

The generated XML is shown below:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <expenseReport>
    <user>
      <userName>Sanaulla</userName>
   </user>
   <items>
     <item>
       <itemName>Seagate External HDD</itemName>
       <purchasedOn>August 24, 2010</purchasedOn>
       <amount>6776.5</amount>
     </item>
   </items>
</expenseReport>

Related Articles:

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

8 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Taq Wave
12 years ago

Hi, your generated XML is missing the namespace information, how do you unmarshal the XSD so that marshalling back to XML has the namespaces?

jcode
jcode
12 years ago

ops

jcode
jcode
12 years ago

Hi!
Great post!
I have a question for you, before create xml I want to validate it with xsd file.
How?
Thanks

rokonoid
rokonoid
10 years ago

is there any tool that can do the reverse, i mean xml to xsd ?

Arka
Arka
9 years ago

I want to show multiple Expense reports by querying from a Database.
How can I do it? Please help me out.

Eklas
Eklas
9 years ago

Hello Mohamed,
this is really amazing, I did not about such tool, I need to convert 100s of XSD to java classes to be able to use jaxb… I started manually, which is time consuming and prone to error… then I found your article… thank you, thank you and thank you very much :)

borntolearn
borntolearn
7 years ago

Good post<

Ajay
Ajay
6 years ago

how to convert excel file to xsd file format

Back to top button