JAXB: ¿Cómo ordenar objetos en listas?


Tal vez una pregunta estúpida: tengo un List de tipo <Data> que quiero mariscal en un archivo XML. Esta es mi clase Database que contiene un 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; }
}

...y estos son los datos de la clase:

// @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; }
}

Utilizando la siguiente clase de prueba...

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"));       
    }
}

...Tengo el resultado:

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

Pero eso no es lo que esperaba, es decir, faltan todas las etiquetas para los objetos <Data>. Estoy buscando una manera de exportar los datos en la siguiente estructura, pero no sé cómo lograr esto:

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

Una pregunta adicional: si quiero tratar el problema sin usando @XmlElementWrapper y @XmlElement anotaciones, puedo introducir una clase intermedia

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

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

Utilizado por la clase base modificada

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

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

En una clase ligeramente modificada Test:

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

El resultado también es:

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

¿Es esta la forma recomendada de crear una estructura de clases Java de acuerdo con la estructura de archivos XML anterior?

Author: user21, 2010-09-10

3 answers

En la propiedad records agregue:

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

Para obtener más información sobre las propiedades de JAXB y collection, consulte:

 92
Author: Blaise Doughan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-19 13:56:31

Esto es en respuesta a su segunda pregunta disquised una respuesta:

Ambos enfoques generarán el mismo XML. Mi recomendación es ir con el modelo que es mejor para su aplicación. Para mí eso generalmente es usar @XmlElementWrapper/@XmlElement. Dado que " registros "solo está ahí para organizar los elementos" datos", realmente no merece su propia clase.

Yo dirijo la implementación de MOXy JAXB y ofrecemos una extensión de mapeo basada en XPath para ir más allá de lo que es capaz con @XmlElementWrapper:

 5
Author: Blaise Doughan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:17:41

En respuesta a su segunda pregunta:

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

Técnicamente hablando, introducir una clase adicional Records para resolver su problema JAXB es un trabajo innecesario y redundante, porque JAXB no lo necesita. El @XmlElementWrapper y @XmlElement name propiedad han sido diseñados para resolver su problema.

De sus comentarios a la respuesta de Blaise, mantengo un tutorial con ejemplos operativos que explican cómo tratar con clases genéricas como List, etc.. cuando unmarshalling.

 4
Author: Jérôme Verstrynge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-07 17:49:37