2011-02-01 20 views
12

por lo que tenemos un tipo XSD en la forma:Lista JAXB Tag creación clase interna

<xs:complexType name="Foo"> 
    <xs:all> 
     <xs:element name="Bars"> 
      <xs:complexType> 
       <xs:sequence> 
        <xs:element name="Bar" type="barType" maxOccurs="unbounded"/> 
       </xs:sequence> 
      </xs:complexType> 
     </xs:element> 
    </xs:all> 
</xs:complexType>  

para representar XML:

<Foo> 
    <!-- Elements snipped for brevity--> 
    <Bars> 
     <Bar> 
      <!-- Bar Element --> 
     </Bar> 
    </Bars> 
</Foo> 

xjc produce resultados casi correctas. Lo único molesto es que "Bars" se crea como una clase interna que almacena una lista de Bars. ¿Hay alguna forma de que Bars sea una lista en Foo mientras se conserva el XML anterior?

Respuesta

1

Se podría hacer lo siguiente:

package example; 

import java.util.List; 

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlElementWrapper; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name="Foo") 
public class Foo { 

    private List<Bar> bar; 

    public List<Bar> getBar() { 
     return bar; 
    } 

    @XmlElementWrapper(name="Bars") 
    @XmlElement(name="Bar") 
    public void setBar(List<Bar> bar) { 
     this.bar = bar; 
    } 

} 

y

package example; 

public class Bar { 

} 

A continuación, puede procesar su XML usando el siguiente código;

package example; 

import java.io.File; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.Unmarshaller; 

public class Demo { 

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

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Foo foo = (Foo) unmarshaller.unmarshal(new File("src/forum128/input.xml")); 

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

Desafortunadamente, estoy tratando de pasar de xsd a los archivos java. – Jim

+0

Estaba buscando algo como esto en [mi pregunta aquí] (http://stackoverflow.com/questions/9240837/how-to-write-my-xsd-in-order-to-match-the-desired-xml -y-java-format-using-jaxb). ¿Se puede generar la anotación '@ XmlElementWrapper' utilizando XJC? Preferiría no modificar manualmente el código generado ... –

+0

Blaise: antes que nada, muchas gracias por todas sus publicaciones y por su blog (por ejemplo [esta publicación] (http://blog.bdoughan.com/2010) /09/jaxb-collection-properties.html) que también se refiere a esto). Siempre súper claro y al grano. Yo también estoy buscando una solución simple (es decir, que no implique un complemento xjc) que nos permita generar '@ XmlElementWrapper' con xjc. Sería muy bueno poder declarar un elemento como "nulo" o "pass-through" en .xsd, es decir, que todos sus subelementos serían automáticamente contenidos por el padre (o más alto si el padre también tiene esa bandera). –

2

Quizás debajo de la muestra ayude.

esquema XML

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

     <xs:complexType name="test"> 
     <xs:sequence> 
      <xs:element name="dataList" type="xs:string" nillable="true" minOccurs="0" maxOccurs="unbounded"/> 
      <xs:element name="str" type="xs:string" minOccurs="0"/> 
     </xs:sequence> 
     </xs:complexType> 
    </xs:schema> 

clase Java:

public class Test { 

    protected List<String> dataList; 
    protected String str; 
    public List<String> getDataList() { 
     if (dataList == null) { 
      dataList = new ArrayList<String>(); 
     } 
     return this.dataList; 
    } 

    public String getStr() { 
     return str; 
    } 

    public void setStr(String value) { 
     this.str = value; 
    } 

} 

EDIT 1:

Puede realizar ingeniería inversa del código Java para xsd. en JAVA_HOME/bin hay schemagen ejecutable.

Proporcione su código java y creará el esquema XSD para usted utilizando su clase java.

see this link

schemagen myObj1.java myObj2.java 
+0

xsd describe como XML (creo), que no es exactamente lo que necesito. – Jim

+0

@Jim Ver mi edición superior. – fmucar

6

Cuando se define Bares como un tipo complejo, Bares se generará como clase separada. De esta manera, encuentro que el esquema también es más fácil de leer. Las barras no serán List en Foo a menos que cambie maxOccurs a un valor superior a 1; no puede hacer esto en xs: all, pero puede usar xs: sequence.

... 
    <xs:complexType name="Foo"> 
     <xs:all> 
      <xs:element name="Bars" type="Bars" /> 
     </xs:all> 
    </xs:complexType> 

    <xs:complexType name="Bars"> 
     <xs:sequence> 
      <xs:element name="Bar" type="barType" maxOccurs="unbounded" /> 
     </xs:sequence> 
    </xs:complexType> 
... 

Después xjc ejecutando: Foo.java:

... 
    @XmlAccessorType(XmlAccessType.FIELD) 
    @XmlType(name = "Foo", propOrder = { 

    }) 
    public class Foo { 

     @XmlElement(name = "Bars", required = true) 
     protected Bars bars; 

     public Bars getBars() { 
      return bars; 
     } 

     public void setBars(Bars value) { 
      this.bars = value; 
     } 
    } 

Bars.java:

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

     @XmlElement(name = "Bar", required = true) 
     protected List<String> bar; 

     ... 
    } 

Con xs: seqence para obtener la lista de Barras (maxOcurrencias = "sin límites"): XSD:

... 
    <xs:complexType name="Foo"> 
     <xs:sequence> 
      <xs:element name="Bars" type="Bars" maxOccurs="unbounded" /> 
     </xs:sequence> 
    </xs:complexType> 

    <xs:complexType name="Bars"> 
     <xs:sequence> 
      <xs:element name="Bar" type="barType" maxOccurs="unbounded" /> 
     </xs:sequence> 
    </xs:complexType> 
    ... 

Foo.java: Plugin de

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

    @XmlElement(name = "Bars", required = true) 
    protected List<Bars> bars; 

    public List<Bars> getBars() { 
     if (bars == null) { 
      bars = new ArrayList<Bars>(); 
     } 
     return this.bars; 
    } 
} 
4

Bjarne Hansen por xjc (https://github.com/dmak/jaxb-xew-plugin) permitiría a quedarse con "barras" elemento que encierra, generando @XmlElementWrapper conveniente (name = "Bares") anotación.

+1

Como se menciona en algunas otras publicaciones/comentarios sobre este tema, ese complemento no parece funcionar con el xjc reciente. He estado golpeando mi cabeza en esto por dos días. También me gusta usar xjc desde la línea de comandos, y este plugin más o menos requiere que escribas un objetivo ant, así como encontrar dónde diablos está el jaxb.jar, etc. –

+0

@PierreD: Si el plugin falla en alguna versión de 'xjc' que necesita, publique en [plugin bugtracker] (https://github.com/dmak/jaxb-xew-plugin/issues). –