¿Cómo puedo agregar atributos xml a la clase anotada de jaxb XmlElementWrapper?


Tengo una clase con una anotación XmlElementWrapper como:

...

  @XmlElementWrapper(name="myList")
    @XmlElements({
    @XmlElement(name="myElement") }
    )
    private List<SomeType> someList = new LinkedList();

... Este código produce XML como

<myList>
  <myElement> </myElement>
  <myElement> </myElement>
  <myElement> </myElement>
</myList>

Hasta ahora todo bien.

Pero ahora necesito agregar atributos a la etiqueta de lista para obtener XML como

<myList number="2">
  <myElement> </myElement>
  <myElement> </myElement>
  <myElement> </myElement>
</myList>

¿Hay una 'manera inteligente de lograr esto sin crear una nueva clase que contenga representa la lista?

Author: Martin Wickman, 2010-09-08

3 answers

Tengo una mejor solución para su pregunta.

Para crear un objeto Xml Java, utilice el siguiente código:

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement(name="myList")
public class Root {

    private String number;
    private List<String> someList;

    @XmlAttribute(name="number")
    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @XmlElement(name="myElement")
    public List<String> getSomeList() {
        return someList;
    }

    public void setSomeList(List<String> someList) {
        this.someList = someList;
    } 

    public Root(String numValue,List<String> someListValue) {
        this();
        this.number = numValue;
        this.someList = someListValue;  
    }

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

}

Para ejecutar el código anterior usando JAXB, use lo siguiente:

   import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.*;

public class Demo {

        public static void main(String[] args) throws Exception {
            List<String> arg = new ArrayList<String>();
            arg.add("FOO");
            arg.add("BAR");
            Root root = new Root("123", arg);

            JAXBContext jc = JAXBContext.newInstance(Root.class);
            Marshaller marshaller = jc.createMarshaller();
            marshaller.marshal(root, System.out);
        }
}

Esto producirá el siguiente XML como salida:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <myList number="123">
        <myElement>FOO</myElement>
        <myElement>BAR</myElement>
    </myList>

Creo que esto es más útil para ti.

Gracias..

 26
Author: Noby George,
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
2011-09-21 10:40:38

La implementación de MOXy JAXB (soy el líder tecnológico) tiene una extensión (@XmlPath ) para manejar este caso:

import java.util.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlPath("myList/@number")
    private int number;

    @XmlElementWrapper(name="myList") 
    @XmlElement(name="myElement") 
    private List<String> someList = new LinkedList<String>();

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public List<String> getSomeList() {
        return someList;
    }

    public void setSomeList(List<String> someList) {
        this.someList = someList;
    } 

}

Producirá el siguiente XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <myList number="123">
      <myElement>FOO</myElement>
      <myElement>BAR</myElement>
   </myList>
</root>

Cuando se ejecuta este código:

import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Root root = new Root();
        root.setNumber(123);
        root.getSomeList().add("FOO");
        root.getSomeList().add("BAR");

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }
}

Para que esto funcione usando código JAXB estrictamente estándar, necesitará usar un adaptador XML:

Nota:

Para usar MOXy JAXB necesita agregar un archivo llamado jaxb.propiedades en con sus clases modelo con la siguiente entrada:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
 11
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
2010-09-08 15:23:23

Si no está utilizando MOXy o simplemente desea atenerse a las anotaciones JAXB estándar, puede extender la respuesta de Noby para agregar soporte para una clase de envoltura genérica. La respuesta de Noby solo soporta actualmente una lista de cadenas, pero digamos por ejemplo que vas a usar la misma clase de envoltura genérica para varias clases diferentes. En mi ejemplo, quiero crear una clase genérica "PagedList" que se marshall a algo que se parece a una lista, pero también contiene información sobre el desplazamiento de la página y el número total de elementos en la lista sin páginas.

El único inconveniente de esta solución es que debe agregar asignaciones @XmlElement adicionales para cada tipo de clase que se empaquetará. En general, sin embargo, probablemente una mejor solución que crear una nueva clase para cada elemento pagable.

@XmlType
public class PagedList<T> {
    @XmlAttribute
    public int offset;

    @XmlAttribute
    public long total;

    @XmlElements({
        @XmlElement(name="order", type=Order.class),
        @XmlElement(name="address", type=Address.class)
        // additional as needed
    })
    public List<T> items;
}

@XmlRootElement(name="customer-profile")
public class CustomerProfile {
    @XmlElement
    public PagedList<Order> orders;
    @XmlElement
    public PagedList<Address> addresses;
}

Organizar este ejemplo te llevaría a:

<customer-profile>
    <order offset="1" total="100">
        <order> ... </order>
        <order> ... </order>
        <order> ... </order>
        ...
    </orders>
    <addresses offset="1" total="5">
        <address> ... </address>
        <address> ... </address>
        <address> ... </address>
        <address> ... </address>
        <address> ... </address>
    <addresses>
</customer-profile>

Espero que eso ayude. Esta es la solución que decidí al menos.

 4
Author: ɲeuroburɳ,
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
2011-12-30 17:12:07