Strs Strs - 1 month ago 10
Java Question

JAXB: Create attribute for inner element

I need to create XML file with following structure:

<Persons>
<Person ID="1">
<Name></Name>
...
</Person>
<Person ID="2">
<Name></Name>
...
</Person>
...
</Persons>


I have already tried all solutions on Stack Overflow, using
*@XmlPath("/Person/@ID")*
,
*@XmlAttribute(name="ID")*
in different ways and had no success. My code creates an attribute in root node or creates additional node before Person node. But attribute should be inside Person node

Method in Main.class:

public void savePersonDataToFile(File file) {
try {
JAXBContext context = JAXBContext
.newInstance(PersonListXMLWrapper.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

// Wrapping our person data.
PersonListXMLWrapper wrapper = new PersonListXMLWrapper();
wrapper.setPersons(personData);

// Marshalling and saving XML to the file.
m.marshal(wrapper, file);

// Save the file path to the registry.
setPersonFilePath(file);
} catch (Exception e) { // catches ANY exception
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Cant save to file:\n" + file.getPath());
alert.setContentText("Ooops, there was an error!");
}
}


Person.class has variable declarations, methods for changing and getting them and constructor:

public class Person {
private final IntegerProperty ID;
private final StringProperty name;
private final StringProperty surname;
private final StringProperty prevSurname;
private final StringProperty patronymic;
...


PersonListXMLWrapper.class:

@XmlRootElement(name = "Persons")
public class PersonListXMLWrapper {

private List<Person> persons;

@XmlElement(name = "Person")
public List<Person> getPersons() {
return persons;
}

public void setPersons(List<Person> persons) {
this.persons = persons;
}


@XmlPath("/Person/@IDAtt")
public String IDAtt ="123";

@XmlAttribute(name="ID")
public String getID() {
return IDAtt;
}

public void setID(String ID) {
this.IDAtt = ID;
}
}

Answer

Solution was extremely simple. I just had to add *@XmlAttribute(name="ID")* to method declaration in Person.class, instead of PersonListXMLWrapper.class:

public class Person {
    private final StringProperty ID;
    private final StringProperty name;
    private final StringProperty surname;
    private final StringProperty prevSurname;
    private final StringProperty patronymic;
    ...

    @XmlAttribute(name="ID")
    public String getID() {
        return ID.get();
    }
    public void setID(String ID) {
        this.ID.set(ID);
    }

    public StringProperty IDProperty() {
        return ID;
    }

So i get the following structure:

<Persons>
    <Person ID="1">
        <name>Name1</name>
        <surname></surname>
        <prevSurname></prevSurname>
        <patronymic></patronymic>
        ...
    </Person>
    <Person ID="2">
        <name>Name2</name>
        <surname></surname>
        <prevSurname></prevSurname>
        <patronymic></patronymic>
        ...
    </Person>
    ...
</Persons>