views:

51

answers:

3

Perhaps a stupid question: i have a List of type <Data> which i want to unmarshall into a XML file. This is my class Database containing an ArrayList...

@XmlRootElement
public class Database
{
    List<Data> records = new ArrayList<Data>();

    public List<Data> getRecords()                   { return records; }
    public void       setRecords(List<Data> records) { this.records = records; }
}

...and this is class Data:

// @XmlRootElement
public class Data 
{
    String name;
    String address;

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

    public String getAddress()               { return address;         }
    public void   setAddress(String address) { this.address = address; }
}

Using the following test class...

public class Test
{
    public static void main(String args[]) throws Exception
    {
        Data data1 = new Data();
             data1.setName("Peter");
             data1.setAddress("Cologne");

        Data data2 = new Data();
             data2.setName("Mary");
             data2.setAddress("Hamburg");

        Database database = new Database();
                 database.getRecords().add(data1);
                 database.getRecords().add(data2);

        JAXBContext context = JAXBContext.newInstance(Database.class);
        Marshaller marshaller = context.createMarshaller();
                   marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                   marshaller.marshal(database, new FileWriter("test.xml"));       
    }
}

...i got the result:

<database>
    <records>
        <address>Cologne</address>
        <name>Peter</name>
    </records>
    <records>
        <address>Hamburg</address>
        <name>Mary</name>
    </records>
</database>

But that's not i was expecting, i.e. all tags for <Data> objects are missing. I am looking for a way to export the data in the following structure, but i don't know how to achieve this:

<database>
    <records>
        <data>
            <address>Cologne</address>
            <name>Peter</name>
        </data>
        <data>
            <address>Hamburg</address>
            <name>Mary</name>
        </data>
    </records>
</database>
+1  A: 

On the records property add:

@XmlElementWrapper(name="records")
@XmlElement(name="data")

For more information on JAXB and collection properties see:

Blaise Doughan
Cool, that's it! Thanks a lot.
rmv
A: 

One additional question: if i want to deal with the problem without using @XmlElementWrapper and @XmlElement annotations, i can introduce an intermediary class

public class Records
{
    List<Data> data = new ArrayList<Data>();

    public List<Data> getData()                { return data; }
    public void       setData(List<Data> data) { this.data = data; }
}

used by the modified base class

@XmlRootElement
public class Database
{
    Records records = new Records();

    public Records getRecords()                { return records; }
    public void    setRecords(Records records) { this.records = records; }
}

in a slightly modified Test class:

        ...
        Database database = new Database();
                 database.getRecords().getData().add(data1);
                 database.getRecords().getData().add(data2);
        ...

The result also is:

<database>
    <records>
        <data>
            <address>Cologne</address>
            <name>Peter</name>
        </data>
        <data>
            <address>Hamburg</address>
            <name>Mary</name>
        </data>
    </records>
</database>

Is this the recommended way to create a Java class structure according to the XML file structure above?

rmv
See http://stackoverflow.com/questions/3683598/jaxb-how-to-unmarshall-objects-in-lists/3686726#3686726
Blaise Doughan
A: 

This is in response to your second question disquised an answer:

Both approaches will generate the same XML. My recommendation is go with the model that is best for your application. For me that is generally using @XmlElementWrapper/@XmlElement. Since "records" is just there to organize the "data" elements it doesn't really deserve its own class.

I lead the MOXy JAXB implementation and we offer an XPath-based mapping extension to go beyond what is capable with @XmlElementWrapper:

Blaise Doughan
It's really quite impressive what's going on in this area. I think i need some time to get in touch with this new mapping technique. Can you give me a first hint, how to read exported XML data into the class structure again? If i use @XmlElementWrapper/@XmlElement for the export, the import program complains that the corresponding classes are (obviously :-) not existing...
rmv
The import (unmarshal) should just work, what exception are you getting?
Blaise Doughan
I think i got an exception that class 'Records' could not be find. But to be sure, i will verify it by an example tomorrow...
rmv
Yes, you are right, unmarshalling works as expected! --- JAXBContext context = JAXBContext.newInstance(Database.class); Unmarshaller unmarshaller = context.createUnmarshaller(); Database database = (Database) unmarshaller.unmarshal(new File("test.xml"));
rmv