2010-03-15 16 views
16

Estoy usando JAXB y xjc para compilar mi esquema XML en clases de Java. No quiero editar manualmente estas clases generadas. Tengo esquema XML así:Cómo generar la anotación de XMLElementWrapper con xjc y el enlace personalizado

<xs:element name="root"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element name="items"> 
     <xs:complexType> 
      <xs:sequence> 
      <xs:element ref="item" /> 
      </xs:sequence> 
     </xs:complexType> 
     </xs:element> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

El xjc genera una clase Items que sólo contiene una lista de objetos Item. ¿Hay alguna posibilidad de omitir la clase Items y tener una lista de objetos Item directamente en la clase Root?

Sé que esto se puede hacer con la anotación @XMLElementWrapper, pero no sé cómo decirle a xjc que cree esto.

¡Gracias por cualquier sugerencia!

Saludos, Markus

Respuesta

11

Bjarne Hansen desarrolló un plugin para xjc que fue capaz de hacerse cargo de esto. Lamentablemente, el enlace a la implementación original ahora está muerto. Sin embargo, hay un proyecto de Dmitry Katsubo en github, basado en el código original de Bjarne con algunas mejoras adicionales.

https://github.com/dmak/jaxb-xew-plugin


(Sólo como referencia: el enlace original, ya muerto: http://www.conspicio.dk/blog/bjarne/jaxb-xmlelementwrapper-plugin)

+0

Thomas, gracias. Este enlace es el primer contenido apropiado que he visto sobre este tema. – mahonya

+0

He intentado durante un tiempo usar ese complemento, pero fue en vano. No estoy seguro si eso es compatible con xjc 2.2.4 (que es lo que tengo en este momento). Además, no tengo el jaxb-xjc.jar (xjc es parte de las herramientas de JDK7). Finalmente, quiero llamar a xjc desde la línea de comandos, y todo el mundo está muy preocupado sobre cómo hacerlo ([Kohsuke Kawaguchi] (http://weblogs.java.net/blog/kohsuke/archive/2005/06/writing_a_plugi.html).) dice "También puedes hacerlo desde la línea de comandos, pero no es muy bonito".) ¿Por qué no podemos tener una jaxb: anotación para decirle a xjc que "omita" un nivel, es decir, que solo generemos un '@ XmlElementWrapper'? –

+0

Tenga en cuenta que mi respuesta es de hace dos años: utilicé el complemento en aquel momento y funcionó bien, pero puede que ya esté desactualizado. – Thomas

8

En primer lugar permite romper el esquema de modo que no hay clases internas generadas:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    elementFormDefault="qualified"> 
    <xs:element name="root" type="Root" /> 

    <xs:complexType name="Root"> 
     <xs:sequence> 
      <xs:element name="items" type="Items" /> 
     </xs:sequence> 
    </xs:complexType> 

    <xs:complexType name="Items"> 
     <xs:sequence> 
      <xs:element name="item" type="xs:string" maxOccurs="unbounded" /> 
     </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

Aún recibirá clases adicionales, pero no todas en un solo archivo. Ahora desea agregar una sección a su compilación para usar el jaxb-xew-plugin. Yo uso de Maven, así que para mí esto se parece a:

<plugin> 
    <groupId>org.jvnet.jaxb2.maven2</groupId> 
    <artifactId>maven-jaxb2-plugin</artifactId> 
    <version>0.8.2</version> 
    <executions> 
     <execution> 
      <goals> 
       <goal>generate</goal> 
      </goals> 
      <configuration> 
       <args> 
        <arg>-no-header</arg> 
        <arg>-Xxew</arg> 
        <arg>-Xxew:instantiate lazy</arg> 
        <arg>-Xxew:delete</arg> 
       </args> 
       <plugins> 
        <plugin> 
         <groupId>com.github.jaxb-xew-plugin</groupId> 
         <artifactId>jaxb-xew-plugin</artifactId> 
         <version>1.0</version> 
        </plugin> 
       </plugins> 
      </configuration> 
     </execution> 
    </executions> 
</plugin> 

Si de empezar a usar espacios de nombres para que sus clases generadas tienen nombres de paquetes, simplemente debe suprimir la bandera -Xxew:delete, ya que hay un error que hace poco me fijo donde fue borrando objetos que no debería. Alternativamente, puede tomar el código de github y usarlo como 1.1-SNAPSHOT.

Cuando hago que consigo el código generado que creo que está buscando:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "Root", propOrder = { 
    "items" 
}) 
public class Root { 

    @XmlElementWrapper(name = "items", required = true) 
    @XmlElement(name = "item") 
    protected List<String> items; 

    public List<String> getItems() { 
     if (items == null) { 
      items = new ArrayList<String>(); 
     } 
     return items; 
    } 

    public void setItems(List<String> items) { 
     this.items = items; 
    } 

} 
Cuestiones relacionadas