Site icon codippa

How to create XML from java objects / Create XML from objects using JAXB

Scenario

Suppose your application fetches a record from a database and it needs to create an XML out of it. There are chances that your application uses an ORM framework such as Hibernate and the database record is fetched in the form of entity classes. Now you have two ways, iterate over the object properties and create each XML node manually using the XML DOM apis (How to create XML from Java program using DOM parser) or follow the approach detailed here.

How ?

The method discussed here uses JAXB (Java Architecture For XML Binding). JAXB is a java framework which has the ability to map classes to XML elements and vice-versa. It provides options to convert java objects to XML and XML to java objects provided they have been properly mapped to each other. The process of converting objects to XML is called marshalling and the conversion of XML to objects is called unmarshalling (How to convert XML to object using JAXB) in JAXB terms.

Suppose you want to create following XML structure from a java program :

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>
<Employees>
<Employee>
<department>dev</department>
<name>codippa</name>
</Employee>
<Employee>
<department>qa</department>
<name>emp1</name>
</Employee>
<Employee>
<department>service</department>
<name>emp2</name>
</Employee>
<Employee>
<department>support</department>
<name>emp3</name>
</Employee>
</Employees>

If you visualize this XML structure and co-relate this with java objects then you can see that this XML is a collection of employees and each employee has two attributes (or fields), department and name. Thus, you can map this XML to two classes

  1. Employees.java – This will be the root of XML and should contain a list of employees.
  2. Employee.java – This class should contain two fields namely department and name.

Let’s design our java classes based on above concept.

Employees.java

 import java.util.List;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;

 @XmlRootElement(name="Employees")
 public class Employees {
   private List<Employee> employee;

   @XmlElement(name="Employee")
   public List<Employee> getEmployee() {
       return employee;
   }

   public void setEmployee(List<Employee> employeeList) {
       this.employee = employeeList;
   }
 }

Details

Employees.java class is annotated with @XmlRootElementwhich implies that it will be the root of the generated XML document. nameattribute of this element specifies the name with which the root node of XML will be created and is optional. If it is not given then root will be created by the name of the class in lower-case letters (that is, employees).

The class also contains a list of Employeeobjects with its getter method annotated with @XmlElementwhich specifies that the elements of this class will be the nodes of the XML with each node named as Employee. Again, the name attribute of this annotation is optional and specifies the name with which the child nodes will be created. If not given, the child nodes will be created by the name of Employeeclass in lower case.

Employee.java

import javax.xml.bind.annotation.XmlElement;

public class Employee {
	
	private String department;

	private String name;
	@XmlElement
	public String getDepartment() {
		return department;
	}

	public void setDepartment(String department) {
		this.department = department;
	}

	@XmlElement
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Details

The above class contains two fields departmentand namewhose getter methods are annotated with @XmlElement.This annotation signifies that these fields will become nodes in the generated XML and will be the children of the class node which contains them. By default the nodes will be created by the name of fields. If you want some other name for the nodes, then provide nameattribute of this annotation with the desired value as shown in Employees class.

 

Moving Ahead

We also need to write code which shall create Employeeobjects, populate their values and adds them to a list. Further, there will also be marshalling code to convert above list of objects to XML. Following code creates the list of employees to be converted to XML:

public static void main(String[] args) throws IOException {
        // create first employee
	Employee e1 = new Employee();
	e1.setName("codippa");
	e1.setDepartment("dev");
        // create second employee
	Employee e2 = new Employee();
	e2.setName("emp1");
	e2.setDepartment("qa");
        // create third employee
	Employee e3 = new Employee();
	e3.setName("emp2");
	e3.setDepartment("service");
        // create fourth employee
	Employee e4 = new Employee();
	e4.setName("emp3");
	e4.setDepartment("support");
        // initialize employee list
	List<Employee> list = new ArrayList<Employee>();
	list.add(e1);
	list.add(e2);
	list.add(e3);
	list.add(e4);
        // initialize root object
	Employees employeeData = new Employees();
        // set employee list
	employeeData.setEmployee(list);
   }

The below code converts the list of employees to XML.

                JAXBContext context = JAXBContext.newInstance(Employees.class);
		Marshaller m = context.createMarshaller();
		// for pretty-print XML in JAXB
		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
		StringWriter writer = new StringWriter();
		// Write to list to a writer
		m.marshal(list, writer);
		String result = writer.toString();
                // write the content to a physical file
		new FileWriter("jaxbTest.xml").write(result);

Details

In order to convert object to XML, first create an object of javax.xml.bind.JAXBContext class using its static newInstancemethod. This method takes a list of one or more top-level classes. Top-level means which should be made the root of generated XML. In our case, it is Employees. Object of javax.xml.bind.JAXBContextis then used to create an object of javax.xml.bind.Marshallar which is responsible for converting java object graph to XML. Its marshalmethod takes the final object which contains all the data to be written to an XML and a java.io.Writerobject. Thus object of any class which extends java.io.Writermay be passed to this method. In above example we pass an object of java.io.StringWriterand the result of marshalling is written to the String which is then written to the file.

Learn How to write String to file in various ways

Let’s tweak in:

  1. @XmlElement annotation may also be applied over field names rather than their getter methods. In that case an annotation @XmlAccessorType(XmlAccessType.FIELD) needs to be applied at the class level.
  2. In order to directly write to a file without using a String, just pass a java.io.FileWriterobject with the appropriate file path to the marshalmethod.
  3. marshalmethod of javax.xml.bind.Marshallertakes a java.io.Writerobject as its second argument which means that you have flexibility of directly writing it to a file or writing it to a string and then writing that string to a file.
  4. If your XML nodes need to have attributes such as of the form <Employee id="1">then this may be achieved by adding an idfield to Employee class and annotating it with @XmlAttributeannotation.
  5. Even if a field in your JAXB annotated classes is not annotated with @XmlElementannotation, it is included in the generated XML by default. If you want to skip a field from being included in the XML, mark it with @XmlTransientannotation.
  6. All JAXB code used above throws javax.xml.bind.JAXBException. Either handle it using try-catch blocks or throw it.
  7. Nodes will be generated by the field or class names in lower-case by default. To change the names of generated nodes, use name attribute alongwith @XmlRootElementor@XmlElementannotations.

Been till Here !!! Move a bit further to comment, share and love this post…

Exit mobile version