Search code examples
javaxmlxml-parsingjaxbjaxb2

Creating an XML with Dynamic Tag names using JAXB


I have to Create an XML using JAXB. But it should have Dynamic tag names. Thats the confusing part in terms of design of POJO's and applying annotation on it.

What should be the POJO structures, and what all annotations should be used on the classes.

The Structure of my desired XML is as follows.

Root Tag is "company", a company has many "departments", each departments has many "sub-departments" which are dynamic, each sub-department has a "manager" , "phone" and "salary".

<company>
    <department>
        <hr>
            <hr-recruitment>
                <manager> Manasa </manager>
                <phone>992222222</phone>
                <salary> 20000 </salary>
            </hr-recruitment>

            <hr-finance>
                <manager> Sunder </manager>
                <phone>993333332</phone>
                <salary> 50000 </salary>
            </hr-finance>
        </hr>
    </department>

    <department>
        <transport>
            <transport-employee>
                <manager> Raman </manager>
                <phone>888888888</phone>
                <salary> 30000 </salary>
            </transport-employee>

            <transport-goods>
                <manager> Sheela </manager>
                <phone>99999999</phone>
                <salary> 75000 </salary>
            </transport-goods>
        </transport>
    </department>

</company> 

Please suggest me the best design of java classes, their elements, and required annotations, with the structure so that i can use Jaxb in my application in a better way.

My current design contains 3 classes.

1) Company 2) Department 3) Branch

The relations are:

1) class Company -has a- List of Departments.
2) class Department -has a- name (String).
3) class Department -has a- List of Branches.
4) class Branch -has a- name (String)
5) class Branch -has a- manager (String)
6) class Branch -has a- phone (String)
7) class Branch -has a- salary (String)

(I have a doubt in efficiency and effectiveness of my above design, please justify its correctness).

Here are the 3 classes marked with the JAXB annotations:

1) company.class

@XmlRootElement(name = "tarang")
public class Company {

    private List<Department> listDepartments;

    public Company(List<Department> listDepartments) {
        this.listDepartments = listDepartments;
    }

    public Company() {

    }

    @XmlElementRef
    public List<Department> getListDepartments() {
        return listDepartments;
    }

    public void setListDepartments(ArrayList<Department> listDepartments) {
        this.listDepartments = listDepartments;
    }

}

2) Department.class

@XmlRootElement(name = "department")
public class Department {

    private String strDepartmentName;

    private List<Branch> listBranchs;

    public Department(String strDepartmentName, List<Branch> listBranchs) {
        this.strDepartmentName = strDepartmentName;
        this.listBranchs = listBranchs;
    }

    public Department() {

    }

    @XmlElement(name = "name")
    public String getStrDepartmentName() {
        return strDepartmentName;
    }

    public void setStrDepartmentName(String strDepartmentName) {
        this.strDepartmentName = strDepartmentName;
    }

    @XmlElementRef
    public List<Branch> getListBranchs() {
        return listBranchs;
    }

    public void setListBranchs(List<Branch> listBranchs) {
        this.listBranchs = listBranchs;
    }

}

3) Branch.class

@XmlRootElement(name = "branch")
public class Branch {

    private String strName;
    private String strManagerName;
    private String strPhone;
    private int intSalary;

    public Branch(String strName, String strManagerName, String strPhone,
            int intSalary) {
        this.strName = strName;
        this.strManagerName = strManagerName;
        this.strPhone = strPhone;
        this.intSalary = intSalary;
    }

    public Branch() {
        // TODO Auto-generated constructor stub
    }

    @XmlElement(name = "name")
    public String getStrName() {
        return strName;
    }

    public void setStrName(String strName) {
        this.strName = strName;
    }

    @XmlElement(name = "manager")
    public String getStrManagerName() {
        return strManagerName;
    }

    public void setStrManagerName(String strManagerName) {
        this.strManagerName = strManagerName;
    }

    @XmlElement(name = "phone")
    public String getStrPhone() {
        return strPhone;
    }

    public void setStrPhone(String strPhone) {
        this.strPhone = strPhone;
    }

    @XmlElement(name = "salary")
    public int getIntSalary() {
        return intSalary;
    }

    public void setIntSalary(int intSalary) {
        this.intSalary = intSalary;
    }

}

The current Output is:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<tarang>
    <department>
        <branch>
            <salary>50000</salary>
            <manager>Manasa</manager>
            <name>hr-recruitment</name>
            <phone>999999999</phone>
        </branch>
        <branch>
            <salary>40000</salary>
            <manager>Sundar</manager>
            <name>hr-finance</name>
            <phone>888888888</phone>
        </branch>
        <name>hr</name>
    </department>
    <department>
        <branch>
            <salary>30000</salary>
            <manager>Raman</manager>
            <name>transport-employee</name>
            <phone>7777777777</phone>
        </branch>
        <branch>
            <salary>20000</salary>
            <manager>Sheela</manager>
            <name>transport-goods</name>
            <phone>6666666666</phone>
        </branch>
        <name>tranport</name>
    </department>
</tarang>

The name of the department, and name of the branch is not getting appended neither as a separate tag, nor as a attribute. Please notify the corrections in annotation markings to get my desired output.


Solution

  • If all the tag names are known in advance, then you could use a combination of @XmlElementRef, @XmlElementDecl, and JAXBElement to map your use case.

    In the long run however you would probably be happier with a more direct representation of your data.

    <?xml version="1.0" encoding="UTF-8"?>
    <company>
        <department name="hr">
            <branch name="hr-recruitment">
                <manager> Manasa </manager>
                <phone>992222222</phone>
                <salary> 20000 </salary>
            </branch>
            <branch name="hr-finance">
                <manager> Sunder </manager>
                <phone>993333332</phone>
                <salary> 50000 </salary>
            </branch>
        </department>
        <department name="transport">
            <branch name="transport-employee">
                <manager> Raman </manager>
                <phone>888888888</phone>
                <salary> 30000 </salary>
            </branch>
            <branch name="transport-goods">
                <manager> Sheela </manager>
                <phone>99999999</phone>
                <salary> 75000 </salary>
            </branch>
        </department>
    </company>