Generation of XML, XSD, DTD With Java

Introduction

 
As you know XML documents play a very significant role in modern projects and product development. Apart from XML documents we encounter jargons like XML schema, XSD and DTD files. There are certain situations where we need to convert a XML document to DTD format or XSD format. There are commercial tools available in the market to provide more clarity on XML, XSD or DTD files. Now the question is whether we can do it using Java. In this article, I provide a glimpse at the Java API for doing the basics of XML file conversion using Java APIs.
 
Technicalities
 
This article is neither about XML, XSD or DTD nor about their features and advantages. In this article, I will present how to generate various XML, XSD or DTD files using Java. As a Java developer we all know how to parse or play with XML files to gather information. In this article, we will learn how to convert XML to XSD or DTD using Java classes. As you know Java provides the API called JAXB through which we can generate a XML document through classes. However, JAXB provides other features also that are unknown to us. This article provides brief outlines of the following items:
  • Java Class to XML
  • Java Class to XSD
  • XML to XSD
  • XML to DTD
  • XSD to Java Classes
  • DTD to Java Classes

Java Class to XML

 
According to JAXB, you can write a plain Java Bean (POJO) and provide the simple JAXB annotations in the class, fields and method levels. You need to populate the Java Bean and provide to JAXB how to generate the XML document. The generation of the XML document from the Java class is called Marshalling. Let us see a small piece of code to become familiar with the JAXB annotations.
  1. package com.ddlab.xml.jaxb.beans;  
  2. import javax.xml.bind.annotation.XmlElement;  
  3. import javax.xml.bind.annotation.XmlElementRef;  
  4. import javax.xml.bind.annotation.XmlRootElement;  
  5. import javax.xml.bind.annotation.XmlType;  
  6. /** 
  7.  * The Class Organisation is used as Java Bean which is root of the XML element. 
  8.  * This class is provided with JAXB annotations to generate XML and XSD file 
  9.  * smoothly. 
  10.  * @author <a href="mailto:[email protected]">Debadatta Mishra</a> 
  11.  * @since 2013 
  12.  */  
  13. @XmlRootElement(name = "Organisation")  
  14. @XmlType(propOrder = { "name""totalEmps""descn""turnOver""emp" })  
  15. public class Organisation {  
  16.       /** The name. */  
  17.       private String name;  
  18.       /** The descn. */  
  19.       private Description descn;  
  20.       /** The total emps. */  
  21.       private int totalEmps;  
  22.       /** The turn over. */  
  23.       private double turnOver = 0d;  
  24.       // ~~ Getter and Setter Methods  
  25.       /** 
  26.        * Gets the descn. 
  27.        * @return the descn 
  28.        */  
  29.       @XmlElement(name = "Description")  
  30.       public Description getDescn() {  
  31.             return descn;  
  32.       }  
  33.       /** 
  34.        * Sets the descn. 
  35.        * 
  36.        * @param descn 
  37.        *            the new descn 
  38.        */  
  39.       public void setDescn(Description descn) {  
  40.             this.descn = descn;  
  41.       }  
  42.       /** The emp. */  
  43.       private Employees emp;  
  44.       /** 
  45.        * Gets the emp. 
  46.        * 
  47.        * @return the emp 
  48.        */  
  49.       @XmlElementRef(type = Employees.class)  
  50.       public Employees getEmp() {  
  51.             return emp;  
  52.       }  
  53.       /** 
  54.        * Sets the emp. 
  55.        * 
  56.        * @param emp 
  57.        *            the new emp 
  58.        */  
  59.       public void setEmp(Employees emp) {  
  60.             this.emp = emp;  
  61.       }  
  62.       /** 
  63.        * Gets the name. 
  64.        * 
  65.        * @return the name 
  66.        */  
  67.       @XmlElement(name = "Name")  
  68.       public String getName() {  
  69.             return name;  
  70.       }  
  71.       /** 
  72.        * Sets the name. 
  73.        * 
  74.        * @param name 
  75.        *            the new name 
  76.        */  
  77.       public void setName(String name) {  
  78.             this.name = name;  
  79.       }  
  80.       /** 
  81.        * Gets the total emps. 
  82.        * 
  83.        * @return the total emps 
  84.        */  
  85.       @XmlElement(name = "TotalEmployees")  
  86.       public int getTotalEmps() {  
  87.             return totalEmps;  
  88.       }  
  89.       /** 
  90.        * Sets the total emps. 
  91.        * 
  92.        * @param totalEmps 
  93.        *            the new total emps 
  94.        */  
  95.       public void setTotalEmps(int totalEmps) {  
  96.             this.totalEmps = totalEmps;  
  97.       }  
  98.       /** 
  99.        * Gets the turn over. 
  100.        * 
  101.        * @return the turn over 
  102.        */  
  103.       @XmlElement(name = "TurnOver")  
  104.       public double getTurnOver() {  
  105.             return turnOver;  
  106.       }  
  107.       /** 
  108.        * Sets the turn over. 
  109.        * 
  110.        * @param turnOver 
  111.        *            the new turn over 
  112.        */  
  113.       public void setTurnOver(double turnOver) {  
  114.             this.turnOver = turnOver;  
  115.       }  
  116.   
  117. }  
Let us see the test code snippet for how to generate the XML contents from the populated Java classes or beans.
  1. Organisation org = getPopulatedBean(); //Get the bean  
  2. ByteArrayOutputStream out = null;  
  3. try {  
  4.     JAXBContext jctx = JAXBContext.newInstance(Organisation.class);  
  5.     Marshaller marshaller = jctx.createMarshaller();  
  6.     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);  
  7.     out = new ByteArrayOutputStream();  
  8.     marshaller.marshal(org, out);  
  9.     String contents = new String(out.toByteArray());  
  10.     System.out.println("---------------Generated XML------------\n"  
  11.         +  
  12.         contents);  
  13. catch (JAXBException e) {  
  14.     System.out.println("JAXB Exception thrown ...");  
  15.     e.printStackTrace();  
  16. catch (Exception ex) {  
  17.     System.out.println("UnExpected Error ...");  
  18.     ex.printStackTrace();  
  19. finally {  
  20.     try {  
  21.         out.close();  
  22.     } catch (IOException e) {  
  23.         e.printStackTrace();  
  24.     }  
  25. }  
This is all about generation of XML documents from Java classes using JAXB annotations.
 

Java Class to XSD

 
This topic seems interesting; how to generate an XML schema directly from Java classes. JAXB also provides a tool called "schemagen" to generate a XML schema in the form of a XSD file. "Schemage" is a part of JDK. If you have installed the JDK and set JAVA_HOME properly then you can type schemagen in the command prompt with the help command. It is always a recommended approach to use the Apache ANT script to generate a XSD file. Schemagen can generate a XSD file if your Java classes are provided with JAXB annotations. If you do not provide JAXB annotations then you will still be able to generate a XSD file. If you do not provide JAXB annotations then it will decide the XML element its own way. Let us see a brief code snippet for the ANT script to generate a XSD file.
  1. <target name="generate.schema" depends="compile">  
  2.       <exec executable="schemagen">  
  3.         <arg line="${class.name}"/>  
  4.         <arg line="-d ${schema.dir}"/>  
  5.         <arg line="-cp ${lib.dir}/org.jar"/>  
  6.       </exec>  
  7. </target>  
The preceding target generates an XSD file in a specified location with the name "schema1.xsd". Based upon the number of classes and namespaces provided in the JAXB annotation, it may generate more than one XSD file. This is the reason "schemagen" does not provide the facility to provide a name for the XSD file. In order to generate the XSD file properly, use the following procedure:
  1. Create all the required Java Beans
  2. Compile all the Java Beans
  3. Create a JAR file out of the compiled classes
  4. Use the required command for the "Schemagen" and provide the name of the JAR file as the path.
Instead of doing it manually, here I have done it using an ANT script that is very easy.
 
XML to XSD
 
XML to XSD conversion has been possible using any commercial tool available in the market. But there was no Java API that directly converts an XML document into an XSD file. There is an API called "trang" that helps to convert XML to XSD. It is free and open source. You can also use an ANT script to generate the XSD file. Let us see the ANT script code snippet below.
 
<exec command="java -jar ${lib.dir}/trang/trang.jar ${xml.dir}/org.xml ${xsd.dir}/org.xsd"/>
 
XML to DTD
 
In this case also, you can generate a DTD file using the "trang" API. I provide the following ANT code snippet to do that.
 
<exec command="java -jar ${lib.dir}/trang/trang.jar ${xml.dir}/org.xml ${dtd.dir}/org.dtd"/>
 
XSD to Java Classes
 
If you have an XSD file and if you are a Java developer then using the Jaxb API you can generate Java classes that you can use to generate the XML file. JAXB provides the "XJC" compiler to compile an XSD file into Java classes. From JDK 6 onwards, the "XJC" compiler is provided with JAXB. It provides a command-line utility and also an ANT script to generate classes. The generation of XML documents from the JAXB generated classes is called "Marshalling" and from XML to a Java object is called "UnMarshalling". Let us consider a typical XSD file as in the following:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">  
  3.   <xs:element name="Organisation">  
  4.     <xs:complexType>  
  5.       <xs:sequence>  
  6.         <xs:element ref="Name"/>  
  7.         <xs:element ref="TotalEmployees"/>  
  8.         <xs:element ref="Description"/>  
  9.         <xs:element ref="TurnOver"/>  
  10.         <xs:element ref="Employees"/>  
  11.       </xs:sequence>  
  12.     </xs:complexType>  
  13.   </xs:element>  
  14.   <xs:element name="TotalEmployees" type="xs:integer"/>  
  15.   <xs:element name="Description">  
  16.     <xs:complexType mixed="true">  
  17.       <xs:attribute name="type" use="required" type="xs:NCName"/>  
  18.       <xs:attribute name="unit" use="required" type="xs:NCName"/>  
  19.     </xs:complexType>  
  20.   </xs:element>  
  21.   <xs:element name="TurnOver" type="xs:decimal"/>  
  22.   <xs:element name="Employees">  
  23.     <xs:complexType>  
  24.       <xs:sequence>  
  25.         <xs:element maxOccurs="unbounded" ref="Emp"/>  
  26.       </xs:sequence>  
  27.     </xs:complexType>  
  28.   </xs:element>  
  29.   <xs:element name="Emp">  
  30.     <xs:complexType>  
  31.       <xs:sequence>  
  32.         <xs:element ref="Address"/>  
  33.         <xs:element ref="Age"/>  
  34.         <xs:element ref="Id"/>  
  35.         <xs:element ref="Name"/>  
  36.         <xs:element ref="Salary"/>  
  37.       </xs:sequence>  
  38.     </xs:complexType>  
  39.   </xs:element>  
  40.   <xs:element name="Address">  
  41.     <xs:complexType>  
  42.       <xs:sequence>  
  43.         <xs:element ref="City"/>  
  44.         <xs:element ref="Country"/>  
  45.         <xs:element ref="StreetName"/>  
  46.       </xs:sequence>  
  47.       <xs:attribute name="Type" use="required" type="xs:NCName"/>  
  48.     </xs:complexType>  
  49.   </xs:element>  
  50.   <xs:element name="City" type="xs:NCName"/>  
  51.   <xs:element name="Country" type="xs:NCName"/>  
  52.   <xs:element name="StreetName" type="xs:NCName"/>  
  53.   <xs:element name="Age" type="xs:integer"/>  
  54.   <xs:element name="Id" type="xs:NCName"/>  
  55.   <xs:element name="Salary" type="xs:decimal"/>  
  56.   <xs:element name="Name" type="xs:string"/>  
  57. </xs:schema>  
To generate the Java classes, let us see the ANT script code snippet below.
  1. <target name="xsd2java" depends="init">  
  2.       <!-- XSD to Java Bean classes -->  
  3.       <exec executable="xjc">  
  4.             <arg line="-xmlschema ${xsd.file.name}"/>  
  5.             <arg line="-d ${gen.dir}"/>  
  6.             <arg line="-p com.ddlab.rnd.xjc.xsd"/>  
  7.       </exec>  
  8. </target>  
The final Java code that will enable us to generate the XML document is given below.
  1. JAXBContext context = JAXBContext.newInstance(Organisation.class);  
  2. Marshaller marshaller = context.createMarshaller();  
  3. marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE);  
  4. marshaller.marshal(org, System.out);  
There are certain situations where you will be given a XSD file to generate the XML file. Any third-party system or subsystem may provide you the XSD file or DTD file to know about the structure of the XML file. This is the only way you can generate the XML. You can benefit from any commercial XML tool to get an idea but it is not recommended to use the XML document in the project development. It is always better to use the API provided by Java.
 

DTD to Java Classes

 
JAXB also provides an experimental API to generate the Java classes from a DTD file. The way JAXB generates the classes from a DTD file is different from that of a XSD file. In the case of a DTD file, JAXB generates more Java classes because of the lack of proper data types in a DTD file. Let use consider a typical DTD file from which we will use JAXB to generate the classes.
  1. <?xml encoding="UTF-8"?>  
  2. <!ELEMENT Organisation (Name,TotalEmployees,Description,TurnOver,  
  3.                         Employees)>  
  4. <!ATTLIST Organisation  
  5.   xmlns CDATA #FIXED ''>  
  6. <!ELEMENT TotalEmployees (#PCDATA)>  
  7. <!ATTLIST TotalEmployees  
  8.   xmlns CDATA #FIXED ''>  
  9. <!ELEMENT Description (#PCDATA)>  
  10. <!ATTLIST Description  
  11.   xmlns CDATA #FIXED ''  
  12.   type NMTOKEN #REQUIRED  
  13.   unit NMTOKEN #REQUIRED>  
  14. <!ELEMENT TurnOver (#PCDATA)>  
  15. <!ATTLIST TurnOver  
  16.   xmlns CDATA #FIXED ''>  
  17. <!ELEMENT Employees (Emp)+>  
  18. <!ATTLIST Employees  
  19.   xmlns CDATA #FIXED ''>  
  20. <!ELEMENT Emp (Address,Age,Id,Name,Salary)>  
  21. <!ATTLIST Emp  
  22.   xmlns CDATA #FIXED ''>  
  23. <!ELEMENT Address (City,Country,StreetName)>  
  24. <!ATTLIST Address  
  25.   xmlns CDATA #FIXED ''  
  26.   Type NMTOKEN #REQUIRED>  
  27. <!ELEMENT Age (#PCDATA)>  
  28. <!ATTLIST Age  
  29.   xmlns CDATA #FIXED ''>  
  30. <!ELEMENT Id (#PCDATA)>  
  31. <!ATTLIST Id  
  32.   xmlns CDATA #FIXED ''>  
  33. <!ELEMENT Salary (#PCDATA)>  
  34. <!ATTLIST Salary  
  35.   xmlns CDATA #FIXED ''>  
  36. <!ELEMENT City (#PCDATA)>  
  37. <!ATTLIST City  
  38.   xmlns CDATA #FIXED ''>  
  39. <!ELEMENT Country (#PCDATA)>  
  40. <!ATTLIST Country  
  41.   xmlns CDATA #FIXED ''>  
  42. <!ELEMENT StreetName (#PCDATA)>  
  43. <!ATTLIST StreetName  
  44.   xmlns CDATA #FIXED ''>  
  45. <!ELEMENT Name (#PCDATA)>  
  46. <!ATTLIST Name  
  47.   xmlns CDATA #FIXED ''>  
In this case you can also use an ANT script to generate the Java classes, the code snippet for the ANT script is given below.
  1. <target name="dtd2java" depends="init">  
  2.       <!-- DTD to Java Bean classes -->  
  3.       <exec executable="xjc">  
  4.             <arg line="-dtd ${dtd.file.name}"/>  
  5.             <arg line="-d ${gen.dir}"/>  
  6.             <arg line="-p com.ddlab.rnd.xjc.dtd"/>  
  7.       </exec>  
  8. </target>  
The only difference you can observe here is to provide the option –dtd for the XJC compiler. After generating the Java classes, in the same way of the "marshaling" approach you can generate the XML documents.
 
If you have a DTD file or XSD file and you want to generate the XML document, you need to use the following procedure:
  1. Create a project for DTD to Java classes or XSD to Java classes.
  2. Create a directory specific to DTD or XSD inside your project.
  3. Write the ANT script that will generate the Java classes from DTD or from XSD file.
  4. Compile the generated Java classes and create the JAR file out of it.
  5. Export the JAR file to your suitable project to use it.
Configuration
 
For a clear understanding and to have a hands-on experience, I have created four projects based on the various concepts explained above. All the four projects are Eclipse projects that can be easily imported into your Eclipse workspace. You can download all the four projects as a single zip file from this site or from dropbox. The link for dropbox is:
 
 
Use the following procedure to work on the attached projects.
  1. Download the zip file and extract to a suitable location. You will find four projects there.
  2. Import each project into your workspace.
  3. Ensure that you Java 6 installed and JAVA_HOME has been set properly.
The project "dtd2java" will help you to understand how to convert a DTD file into Java classes and the "test" source folder has a sample Java test class to generate the XML document.
 
The project "xsd2java" will help you to understand how to convert a XSD file into Java classes and the "test" source folder has a sample Java test class to generate the XML document.
 
The project "xml2xsddtd" will show you how to convert a XML to DTD and XSD using "trang". This project contains an ANT script that can be run in the Eclipse IDE to generate the DTD and XSD file.
 
The project "xmlconversions1" will help you understand the usage of "schemagen" and generation of XML from Java classes.
 
To use the "trang" API, you can download "trang" from the following:
 
 
Conclusion
 
I hope you have enjoyed my article about the various XML conversions and generation of XML documents. Download the complete project and go through the source code to understand the concept and its usage. Based upon the complexity and design, you can decide whether to use this concept. For any kind of issues and errors you can contact me at [email protected] .
 
References
 
Refer to the following links to learn more.