Delumees
Delumees

Reputation: 35

JAXB - Make nested child element from Java object filed

I am trying to generate an XML file from Java object via JAXB. I have the following Java class:

@XmlRootElement
public class StudentsInfo {

    String university;
    String faculty;
    long facultyNumber;
    int degree;
    String specialty;

    public String getUniversity() {
        return university;
    }
    @XmlElement
    public void setUniversity(String university) {
        this.university = university;
    }

    public String getFaculty() {
        return faculty;
    }
    @XmlElement
    public void setFaculty(String faculty) {
        this.faculty = faculty;
    }

    public long getFacultyNumber() {
        return facultyNumber;
    }
    @XmlElement
    public void setFacultyNumber(long facultyNumber) {
        this.facultyNumber = facultyNumber;
    }

    public int getDegree() {
        return degree;
    }
    @XmlElement
    public void setDegree(int degree) {
        this.degree = degree;
    }

    public String getSpecialty() {
        return specialty;
    }
    @XmlElement
    public void setSpecialty(String specialty) {
        this.specialty = specialty;
    }
}

Then in other class with main() method I do this:

StudentsInfo studentsInfo = new StudentsInfo();
        studentsInfo.setFaculty("university name");
        studentsInfo.setFaculty("faculty name");
        studentsInfo.setFacultyNumber(1234);
        studentsInfo.setDegree(1);
        studentsInfo.setSpecialty("specialty name");

        // create an XML from studentsInfo
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(StudentsInfo.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            // output pretty printed
            jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

            StringWriter sw = new StringWriter();
            jaxbMarshaller.marshal(studentsInfo, sw);
            String stringXML = sw.toString();
            System.out.println(stringXML);
        } catch (JAXBException e) { e.printStackTrace(); }

So JAXB generates the following XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<studentsInfo>
    <degree>1</degree>
    <faculty>faculty name</faculty>
    <facultyNumber>1234</facultyNumber>
    <specialty>specialty name</specialty>
    <university>university name</university>
</studentsInfo>

But actually I want it to generate XML with another hierarchy - I want to make nested XML tags from some fields, for example:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<studentsInfo>
    <!-- I want to have some nested elements like these for example: -->
    <university name="university name">
        <faculty>faculty name</faculty>
        <facultyNumber>1234</facultyNumber>
        <specialty>specialty name</specialty>
    </university>

    <degree>1</degree>

</studentsInfo>

So is there any way to do this, without having to create new Java classes and subclasses? Because the real code is much longer than this and has many more fields and I can't rewrite it from the beginning..

Upvotes: 2

Views: 1397

Answers (1)

Cfx
Cfx

Reputation: 2312

Seems I have a solution, but not using JAXB. If this is not an option, I will delete my answer. When you use data projection instead of data binding, e.g with XMLBeam (Disclosure: I'm affiliated with that project) you can decouple the Java and the XML structure like this:

public class CreateStudentsInfo {

public interface StudentsInfo{

    @XBWrite("/studentsInfo/university/@name")
    StudentsInfo setUniversityName(String universityName);

    @XBWrite("/studentsInfo/university/faculty")
    StudentsInfo setFacultyName(String facultyName);

    @XBWrite("/studentsInfo/university/facultyNumber")
    StudentsInfo setFacultyNumber(int facultyNumber);

    @XBWrite("/studentsInfo/university/specialty")
    StudentsInfo setSpecialty(String specialtyName);

    @XBWrite("/studentsInfo/degree")
    StudentsInfo setDegree(int degree);
}

public static void main(String[] args) {        
    StudentsInfo studentsInfo = new XBProjector(Flags.TO_STRING_RENDERS_XML).projectEmptyDocument(StudentsInfo.class);
    studentsInfo.setUniversityName("university name").setFacultyName("faculty name").setFacultyNumber(1234);
    studentsInfo.setSpecialty("speciality name").setDegree(1);
    System.out.println(studentsInfo);
 }
}

This program prints out:

<studentsInfo>
  <university name="university name">
    <faculty>faculty name</faculty>
    <facultyNumber>1234</facultyNumber>
    <specialty>speciality name</specialty>
  </university>
  <degree>1</degree>
</studentsInfo>

Upvotes: 1

Related Questions