2010-04-26 17 views
9

J'utilise xjc pour générer des classes Java à partir du schéma XML et ce qui suit est un extrait de la XSD.XML Schema to Java Classes avec XJC

<xs:element name="NameInfo"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:choice> 
     <xs:element ref="UnstructuredName"/> <!-- This line --> 
     <xs:sequence> 
      <xs:element ref="StructuredName"/> 
      <xs:element ref="UnstructuredName" minOccurs="0"/> <!-- and this line! --> 
     </xs:sequence> 
     </xs:choice> 
     <xs:element ref="SomethingElse" minOccurs="0"/> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

Pour la plupart des classes générées sont très bien, mais pour le bloc ci-dessus je recevrais quelque chose comme:

public List<Object> getContent() { 
    if (content == null) { 
    content = new ArrayList<Object>(); 
    } 
    return this.content; 
} 

avec le commentaire suivant au-dessus:

* You are getting this "catch-all" property because of the following reason: 
* The field name "UnstructuredName" is used by two different parts of a schema. See: 
* line XXXX of file:FILE.xsd 
* line XXXX of file:FILE.xsd 
* To get rid of this property, apply a property customization to one 
* of both of the following declarations to change their names: 
* Gets the value of the content property. 

Je placé un commentaire à la fin de la ligne en question.

Pour l'instant, je ne pense pas qu'il sera facile de changer le schéma puisque cela a été décidé entre les fournisseurs et je ne voudrais pas aller sur cette route (si possible) car cela ralentirait un peu les progrès.

J'ai cherché et j'ai trouvé this page, est la personnalisation externe ce que je veux faire? J'ai surtout travaillé avec les classes générées, donc je ne suis pas entièrement familier avec le processus qui génère ces classes. Un exemple simple de la "personnalisation de la propriété" serait génial! Une méthode alternative de génération des classes Java serait bien tant que le schéma peut encore être utilisé.

EDIT: Je dois préciser que les deux UnstructuredName sont en effet le même élément.

Répondre

1

Le problème essentiel ici est que vous avez un <xs:sequence> constitué d'un <xs:choice>, qui se traduit en Java par "un List de choses". La structure de type de Java n'est pas assez flexible pour représenter ceci mieux.

Une personnalisation de liaison pourrait peut-être vous aider, mais dans ce cas, je ne crois pas, car je ne peux pas voir une meilleure façon de représenter cette information. Une autre technique que j'ai utilisée dans le passé est de passer d'abord le schéma à travers une simple transformation XSLT, en réorganisant les composants en quelque chose de plus JAXB, tout en permettant les mêmes structures que les documents auront en réalité . De cette façon, vous pouvez "changer" le schéma sans changer l'original.

+0

Je ne suis pas tout à fait sûr de savoir comment réarranger les éléments peut aider dans ce cas. Si je peux la "séquence" intérieure dans un autre élément, ce problème serait résolu? Est-ce faisable avec la transformation? Si j'effectue une transformation, j'en aurais besoin d'une pour la transformer en une structure que j'aime et ensuite effectuer une autre transformation dans sa structure d'origine? – nevets1219

2

J'ai eu le même problème. Je suis passé à xmlbeans et axis. XMLBeans peut compiler votre schéma sans problème et sans mal de tête. JaxB ne peut pas gérer cela. Pour que JaxB gère cela, vous pouvez changer un peu votre schéma.

<xs:sequence> 
      <xs:choice> 
    <!-- changed the following line --> 
      <xs:element name="UnstructuredTop" type="UnstructuredName"/> 
    <!-- end of change --> 
      <xs:sequence> 
       <xs:element ref="StructuredName"/> 
       <xs:element ref="UnstructuredName" minOccurs="0"/> 
      </xs:sequence> 
      </xs:choice> 
      <xs:element ref="SomethingElse" minOccurs="0"/> 
    </xs:sequence> 

Ensuite, JaxB va distinguer les deux et ne pas flip out.

Cependant votre situation est comme ma situation. Changer le schéma était hors de question. Donc je suis allé avec xmlBeans et axis (qui sux).

5

Vous pouvez également utiliser une personnalisation de liaison appelé <xjc:simple />:

<?xml version="1.0" encoding="UTF-8"?> 
<jxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
       jxb:version="2.0"> 
     <jxb:globalBindings> 
      <xjc:simple /> 
     </jxb:globalBindings> 
</jxb:bindings> 

S'il vous plaît cependant être conseillé que c'est spécifique du fournisseur (qui utilise quelque chose d'autre que XJC bien;))

Plus d'info here

0

J'ai créé une classe wrapper pour résoudre le problème:

List<JAXBElement<?>> contentList = address.getContent(); 
if (contentList != null && contentList.size() > 0) { 
    Address4JaxbMula address4JaxbMula = new Address4JaxbMula(contentList); 

...}

...

public static class Address4JaxbMula { 
    public CountryCodeType countryCode; 
    public AddressFixType addressFix; 
    public String addressFree; 

    public Address4JaxbMula(List<JAXBElement<?>> contentList) { 
     if (contentList != null && contentList.size() > 0) { 
      for (JAXBElement<?> content : contentList) { 
       Object value = content.getValue(); 
       if (value.getClass().isAssignableFrom(CountryCodeType.class)) { 
        countryCode = (CountryCodeType) content.getValue(); 
       } else if (value.getClass().isAssignableFrom(AddressFixType.class)) { 
        addressFix = (AddressFixType) content.getValue(); 
       } else { 
        addressFree = (String) value; 
       } 
      } 
     } 
    } 

}