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.
Let us see the test code snippet for how to generate the XML contents from the populated Java classes or beans.
- Organisation org = getPopulatedBean();
- ByteArrayOutputStream out = null;
- try {
- JAXBContext jctx = JAXBContext.newInstance(Organisation.class);
- Marshaller marshaller = jctx.createMarshaller();
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
- out = new ByteArrayOutputStream();
- marshaller.marshal(org, out);
- String contents = new String(out.toByteArray());
- System.out.println("---------------Generated XML------------\n"
- +
- contents);
- } catch (JAXBException e) {
- System.out.println("JAXB Exception thrown ...");
- e.printStackTrace();
- } catch (Exception ex) {
- System.out.println("UnExpected Error ...");
- ex.printStackTrace();
- } finally {
- try {
- out.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
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.
- <target name="generate.schema" depends="compile">
- <exec executable="schemagen">
- <arg line="${class.name}"/>
- <arg line="-d ${schema.dir}"/>
- <arg line="-cp ${lib.dir}/org.jar"/>
- </exec>
- </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:
-
Create all the required Java Beans
-
Compile all the Java Beans
-
Create a JAR file out of the compiled classes
-
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:
- <?xml version="1.0" encoding="UTF-8"?>
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:element name="Organisation">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="Name"/>
- <xs:element ref="TotalEmployees"/>
- <xs:element ref="Description"/>
- <xs:element ref="TurnOver"/>
- <xs:element ref="Employees"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="TotalEmployees" type="xs:integer"/>
- <xs:element name="Description">
- <xs:complexType mixed="true">
- <xs:attribute name="type" use="required" type="xs:NCName"/>
- <xs:attribute name="unit" use="required" type="xs:NCName"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="TurnOver" type="xs:decimal"/>
- <xs:element name="Employees">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="Emp"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="Emp">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="Address"/>
- <xs:element ref="Age"/>
- <xs:element ref="Id"/>
- <xs:element ref="Name"/>
- <xs:element ref="Salary"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="Address">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="City"/>
- <xs:element ref="Country"/>
- <xs:element ref="StreetName"/>
- </xs:sequence>
- <xs:attribute name="Type" use="required" type="xs:NCName"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="City" type="xs:NCName"/>
- <xs:element name="Country" type="xs:NCName"/>
- <xs:element name="StreetName" type="xs:NCName"/>
- <xs:element name="Age" type="xs:integer"/>
- <xs:element name="Id" type="xs:NCName"/>
- <xs:element name="Salary" type="xs:decimal"/>
- <xs:element name="Name" type="xs:string"/>
- </xs:schema>
To generate the Java classes, let us see the ANT script code snippet below.
- <target name="xsd2java" depends="init">
-
- <exec executable="xjc">
- <arg line="-xmlschema ${xsd.file.name}"/>
- <arg line="-d ${gen.dir}"/>
- <arg line="-p com.ddlab.rnd.xjc.xsd"/>
- </exec>
- </target>
The final Java code that will enable us to generate the XML document is given below.
- JAXBContext context = JAXBContext.newInstance(Organisation.class);
- Marshaller marshaller = context.createMarshaller();
- marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE);
- 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.
- <?xml encoding="UTF-8"?>
- <!ELEMENT Organisation (Name,TotalEmployees,Description,TurnOver,
- Employees)>
- <!ATTLIST Organisation
- xmlns CDATA #FIXED ''>
- <!ELEMENT TotalEmployees (#PCDATA)>
- <!ATTLIST TotalEmployees
- xmlns CDATA #FIXED ''>
- <!ELEMENT Description (#PCDATA)>
- <!ATTLIST Description
- xmlns CDATA #FIXED ''
- type NMTOKEN #REQUIRED
- unit NMTOKEN #REQUIRED>
- <!ELEMENT TurnOver (#PCDATA)>
- <!ATTLIST TurnOver
- xmlns CDATA #FIXED ''>
- <!ELEMENT Employees (Emp)+>
- <!ATTLIST Employees
- xmlns CDATA #FIXED ''>
- <!ELEMENT Emp (Address,Age,Id,Name,Salary)>
- <!ATTLIST Emp
- xmlns CDATA #FIXED ''>
- <!ELEMENT Address (City,Country,StreetName)>
- <!ATTLIST Address
- xmlns CDATA #FIXED ''
- Type NMTOKEN #REQUIRED>
- <!ELEMENT Age (#PCDATA)>
- <!ATTLIST Age
- xmlns CDATA #FIXED ''>
- <!ELEMENT Id (#PCDATA)>
- <!ATTLIST Id
- xmlns CDATA #FIXED ''>
- <!ELEMENT Salary (#PCDATA)>
- <!ATTLIST Salary
- xmlns CDATA #FIXED ''>
- <!ELEMENT City (#PCDATA)>
- <!ATTLIST City
- xmlns CDATA #FIXED ''>
- <!ELEMENT Country (#PCDATA)>
- <!ATTLIST Country
- xmlns CDATA #FIXED ''>
- <!ELEMENT StreetName (#PCDATA)>
- <!ATTLIST StreetName
- xmlns CDATA #FIXED ''>
- <!ELEMENT Name (#PCDATA)>
- <!ATTLIST Name
- 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.
- <target name="dtd2java" depends="init">
-
- <exec executable="xjc">
- <arg line="-dtd ${dtd.file.name}"/>
- <arg line="-d ${gen.dir}"/>
- <arg line="-p com.ddlab.rnd.xjc.dtd"/>
- </exec>
- </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:
-
Create a project for DTD to Java classes or XSD to Java classes.
-
Create a directory specific to DTD or XSD inside your project.
-
Write the ANT script that will generate the Java classes from DTD or from XSD file.
-
Compile the generated Java classes and create the JAR file out of it.
-
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.
-
Download the zip file and extract to a suitable location. You will find four projects there.
-
Import each project into your workspace.
-
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.