Tuesday, December 3, 2013

Transform Object into XML using JAXB (Part 2)

In one of the posts we had seen how to convert Java objects into XML. This was done using JAXB and XSD

What if you don't like to write XSD by hand. Well, you can use any online or offline tools available, to generate the desired XSD from XML. Most of the times the generated XSD will be nearly accurate and you have to hand edit them to make it 100% perfect.

Alright. What if you don't know XSD at all. Is there a simpler way? Yes there is.

Here we are going to use a different approach to achieve exactly the same result that we have got in the old post.

Open Netbeans and create a Java Application
  • File->New Project->Java Application
  • Enter "XMLBinding2" in the Project Name field
  • Click Finish
  • Create the following Java classes

Replace the Java files with the following contents appropriately.

package xmlbinding2;

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

@XmlRootElement
public class Report {

    private List<Student> students;

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }
}

package xmlbinding2;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Student {

    private String name;
    private Marks marks;

    public String getName() {
        return name;
    }

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

    public Marks getMarks() {
        return marks;
    }

    public void setMarks(Marks marks) {
        this.marks = marks;
    }
}

package xmlbinding2;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Marks {

    private int maths;
    private int physics;
    private int chemistry;
    private int biology;

    public int getMaths() {
        return maths;
    }

    public void setMaths(int maths) {
        this.maths = maths;
    }

    public int getPhysics() {
        return physics;
    }

    public void setPhysics(int physics) {
        this.physics = physics;
    }

    public int getChemistry() {
        return chemistry;
    }

    public void setChemistry(int chemistry) {
        this.chemistry = chemistry;
    }

    public int getBiology() {
        return biology;
    }

    public void setBiology(int biology) {
        this.biology = biology;
    }
}

Create the main class as in the last post, but with slight modification as shown below.

package xmlbinding2;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class XmlBinding2 {

    public static void main(String[] args) throws JAXBException {
        Report report = new Report();
        List<Student> students = new ArrayList<>();
        Student student = new Student();
        student.setName("Lydia");
        Marks marks = new Marks();
        marks.setMaths(100);
        marks.setPhysics(98);
        marks.setChemistry(85);
        marks.setBiology(93);
        student.setMarks(marks);
        students.add(student);

        student = new Student();
        student.setName("Angel");
        marks = new Marks();
        marks.setMaths(100);
        marks.setPhysics(88);
        marks.setChemistry(95);
        marks.setBiology(94);
        student.setMarks(marks);
        students.add(student);

        report.setStudents(students);

        JAXBContext jaxbContext = JAXBContext.newInstance(Report.class);
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(report, System.out);
    }
}

Run the project. You will see the following output.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<report>
    <students>
        <marks>
            <biology>93</biology>
            <chemistry>85</chemistry>
            <maths>100</maths>
            <physics>98</physics>
        </marks>
        <name>Lydia</name>
    </students>
    <students>
        <marks>
            <biology>94</biology>
            <chemistry>95</chemistry>
            <maths>100</maths>
            <physics>88</physics>
        </marks>
        <name>Angel</name>
    </students>
</report>

There is a little difference between the output that we have got here and in old post. The <student> tag is missing. Let's try to make them same.

Add the following two annotations to the Report.getStudents() method.

    @XmlElementWrapper(name = "students")
    @XmlElement(name = "student")

Your Report.java class will now look like the following.
package xmlbinding2;

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

@XmlRootElement
public class Report {

    private List<Student> students;

    @XmlElementWrapper(name = "students")
    @XmlElement(name = "student")
    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }
}

Here is the output.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<report>
    <students>
        <student>
            <marks>
                <biology>93</biology>
                <chemistry>85</chemistry>
                <maths>100</maths>
                <physics>98</physics>
            </marks>
            <name>Lydia</name>
        </student>
        <student>
            <marks>
                <biology>94</biology>
                <chemistry>95</chemistry>
                <maths>100</maths>
                <physics>88</physics>
            </marks>
            <name>Angel</name>
        </student>
    </students>
</report>

Is it same as the old post. Yes it is!