web-dev-qa-db-fra.com

Générer des classes Java à partir de fichiers .XSD ...?

J'ai un gigantesque fichier de schéma .XSD du SDK QuickBooks qui définit les requêtes/réponses XML que je peux envoyer/recevoir de QuickBooks.

J'aimerais pouvoir générer facilement des classes Java à partir de ces fichiers .XSD, que je pourrais ensuite utiliser pour marshaler XML en Java objets et Java. objets en XML.

Y a-t-il un moyen facile de faire ceci...?

Idéalement, aucune bibliothèque externe à la distribution de base Java au moment de l'exécution ne serait nécessaire. Mais je suis flexible ...

122
Keith Palmer Jr.

JAXB fait EXACTEMENT ce que vous voulez. Il est intégré au JRE/JDK à partir de 1,6.

119
basszero

Pour développer les commentaires "utiliser JAXB" ci-dessus,

Sous Windows "%Java_home%\bin\xjc" -p [your namespace] [xsd_file].xsd

par exemple, "%Java_home%\bin\xjc" -p com.mycompany.quickbooks.obj quickbooks.xsd

Attendez un peu, et si vous avez un fichier XSD bien formé, vous obtiendrez des classes Java bien formées.

116
Ed Norris

Si vous souhaitez commencer à coder Java en XML et XML en Java en moins de 5 minutes, essayez la sérialisation XML simple. Ne passez pas des heures à apprendre l’API JAXB http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php

Toutefois, si vous souhaitez vraiment apprendre JAXB, voici un excellent tutoriel http://blogs.Oracle.com/teera/entry/jaxb_for_simple_Java_xml

Contenu du tutoriel:

JAXB pour la sérialisation Java-XML simple

Il existe un certain nombre de façons de réaliser la sérialisation XML en Java. Si vous souhaitez un contrôle plus fin de l'analyse et de la sérialisation, optez pour SAX, DOM ou Stax pour de meilleures performances. Cependant, ce que je veux souvent faire est un simple mappage entre POJO et XML. Cependant, créer des classes Java pour analyser manuellement les événements XML n'est pas trivial. JAXB s’est récemment révélé être un mappage ou une sérialisation Java-XML rapide et pratique.

JAXB contient de nombreuses fonctionnalités utiles, vous pouvez consulter l'implémentation de référence ici. Blog de Kohsuke est également une bonne ressource pour en savoir plus sur JAXB. Pour cette entrée de blog, je vais vous montrer comment effectuer une sérialisation Java-XML simple avec JAXB.

POJO to XML

Disons que j'ai un objet Item Java. Je veux sérialiser un objet Item au format XML. Ce que je dois faire en premier lieu, c'est d'annoter ce POJO avec quelques annotations XML du paquet javax.xml.bind.annotation. *. Voir liste de codes 1 pour Item.Java

Du code

  • @XmlRootElement(name="Item") indique que je veux être l'élément racine.
  • @XmlType(propOrder = {"name", "price"}) indique l'ordre dans lequel je souhaite que l'élément soit organisé en sortie XML.
  • @XmlAttribute(name="id", ...) indique que id est un attribut de l'élément racine.
  • @XmlElement(....) indique que je souhaite que le prix et le nom soient des éléments de l'élément.

Mon Item.Java est prêt. Je peux ensuite créer un script JAXB pour le marshaling Item.

//creating Item data object
Item item = new Item();
item.setId(2);
item.setName("Foo");
item.setPrice(200);
.....

JAXBContext context = JAXBContext.newInstance(item.getClass());
Marshaller marshaller = context.createMarshaller();
//I want to save the output file to item.xml
marshaller.marshal(item, new FileWriter("item.xml"));

Pour une liste complète des codes, veuillez vous reporter à la liste des codes 2 main.Java. Le fichier de sortie de la liste de codes 3 item.xml est créé. Cela ressemble à ceci:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:item ns1:id="2" xmlns:ns1="http://blogs.Sun.com/teera/ns/item">

 <ns1:itemName>Foo</ns1:itemName>
<ns1:price>200</ns1:price>

</ns1:item>

Facile non? Vous pouvez également canaliser le code XML de sortie sous forme de chaîne de texte, flux, enregistreur, ContentHandler, etc. en modifiant simplement le paramètre de la méthode marshal (...) comme

...
JAXBContext context = JAXBContext.newInstance(item.getClass());
Marshaller marshaller = context.createMarshaller();
// save xml output to the OutputStream instance
marshaller.marshal(item, <Java.io.OutputStream instance>);

...
JAXBContext context = JAXBContext.newInstance(item.getClass());
Marshaller marshaller = context.createMarshaller();
StringWriter sw = new StringWriter();
//save to StringWriter, you can then call sw.toString() to get Java.lang.String
marshaller.marshal(item, sw);

XML en POJO

Inversons le processus. Supposons que je dispose maintenant d’un morceau de données de chaîne XML et que je souhaite le transformer en objet Item.Java. Les données XML (liste de code 3) ressemblent à

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:item ns1:id="2" xmlns:ns1="http://blogs.Sun.com/teera/ns/item">
<ns1:itemName>Bar</ns1:itemName>
<ns1:price>80</ns1:price>
</ns1:item>

Je peux alors démarquer ce code xml en objet Item par

...
ByteArrayInputStream xmlContentBytes = new ByteArrayInputStream (xmlContent.getBytes());
JAXBContext context = JAXBContext.newInstance(Item.getClass());
Unmarshaller unmarshaller = context.createUnmarshaller();
//note: setting schema to null will turn validator off
unmarshaller.setSchema(null);
Object xmlObject = Item.getClass().cast(unmarshaller.unmarshal(xmlContentBytes));
return xmlObject;
...

Pour une liste complète des codes, veuillez vous reporter à la liste des codes 2 (main.Java). La source XML peut prendre de nombreuses formes à la fois à partir de Stream et de fichier. Encore une fois, la seule différence est le paramètre method:

...
unmarshaller.unmarshal(new File("Item.xml")); // reading from file
...
// inputStream is an instance of Java.io.InputStream, reading from stream
unmarshaller.unmarshal(inputStream);

Validation avec XML Schema

La dernière chose que je veux mentionner ici est la validation du XML d’entrée avec le schéma avant de procéder à une restarution à l’objet Java. Je crée un fichier de schéma XML appelé item.xsd. Pour une liste complète des codes, veuillez vous reporter à la liste des codes 4 (Item.xsd). Maintenant, ce que je dois faire, c'est enregistrer ce schéma pour validation.

...
Schema schema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
.newSchema(new File("Item.xsd"));
unmarshaller.setSchema(schema); //register item.xsd shcema for validation
...

Lorsque j'essaie de disséminer les données XML en POJO, si le XML d'entrée n'est pas conforme au schéma, une exception sera interceptée. Pour une liste complète des codes, veuillez vous reporter à la liste des codes 5 (invalid_item.xml).

javax.xml.bind.UnmarshalException
- with linked exception:
javax.xml.bind.JAXBException caught: null
[org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'item1' is
                                not a valid value for 'integer'.]

Ici, je change l'attribut 'id' en chaîne plutôt qu'en entier.

Si l'entrée XML est valide par rapport au schéma, les données XML seront correctement décomposées en objet Item.Java.

37
Aries McRae

En utilisant Eclipse IDE: -

  1. copier le xsd dans un projet nouveau/existant.
  2. Assurez-vous que vous avez les fichiers JAR requis par JAXB dans votre chemin de classe. Vous pouvez en télécharger un ici .
  3. Faites un clic droit sur le fichier XSD -> Générer -> Classes JAXB.
29
Kumar Sambhav

le moyen le plus simple est d'utiliser la ligne de commande. Il suffit de taper dans le répertoire de votre fichier .xsd:

xjc myFile.xsd.

Ainsi, le Java générera tous les Pojos.

16
Willian Crozeta

XMLBeans le fera. Plus précisément, la commande "scomp".

EDIT: XMLBeans a été retiré , cochez cet article stackoverflow pour plus d'informations.

14
TofuBeer

Maven peut être utilisé à cet effet, vous devez ajouter des dépendances et simplement nettoyer votre application. Vous obtiendrez toutes les classes créées automatiquement dans votre dossier cible.

Copiez-les simplement de la cible à l’endroit désiré, voici le fichier pom.xml que j’ai utilisé pour créer une classification à partir de fichiers xsd:

    <plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>jaxb2-maven-plugin</artifactId>

     <executions>
      <execution>
       <goals>
        <goal>xjc</goal>
       </goals>
      </execution>
     </executions>
     <configuration>
      <schemaDirectory>src/main/webapp/schemas/</schemaDirectory>
     </configuration>
    </plugin>

   </plugins>
  </pluginManagement>
 </build>
</project>

Il suffit de placer vos fichiers xsd sous "src/main/webapp/schemas /" et Maven les trouvera au moment de la compilation.

J'espère que cela vous aidera. Pour plus d'informations, visitez le site http://www.beingjavaguys.com/2013/04/create-spring-web-services-using-maven.html

J'espère que ça va aider :)

12
neel4soft

Si cela ne vous dérange pas d'utiliser une bibliothèque externe, j'ai déjà utilisé Castor pour le faire par le passé.

7
Marc Novakowski

La meilleure option est %Java_home%\bin\xjc -p [your namespace] [xsd_file].xsd.

J'ai également une question si nous avons une option pour faire de l'ingénierie inverse ici. si oui pouvons-nous générer xsd à partir de la classe pojo?

7
sree

JAXB Limitation.

JAXB, j’ai travaillé à mon sens, c’est une façon agréable de traiter les données entre XML et les objets Java. Les côtés positifs sont ses performances éprouvées et meilleures et le contrôle des données pendant l'exécution. Avec une bonne utilisation des outils construits ou des scripts, il faudra beaucoup d'efforts de codage.

J'ai trouvé que la partie configuration n'était pas une tâche immédiate et j'ai passé des heures à configurer l'environnement de développement.

Cependant, j'ai abandonné cette solution en raison d'une limitation stupide à laquelle je faisais face. Ma définition de schéma XML (XSD) a un attribut/élément avec le nom "value" et je dois utiliser XSD tel quel. Cette très petite contrainte a forcé l'étape de ma liaison XJC a échoué avec une erreur "Propriété 'Valeur' ​​déjà utilisée."

En raison de l'implémentation JAXB, le processus de liaison tente de créer des objets Java à partir de XSD en ajoutant quelques attributs à chaque classe, l'un d'eux étant un attribut value. Lors du traitement de mon XSD, il s'est plaint de l'existence d'une propriété portant ce nom.

5
RAm

Le XJC de JAXB n’est-il pas une réponse possible à cela? J'essaie de faire la même chose. Toujours dans la phase "essayer" cependant. Entré à travers XJC, alors pensé à partager.

4
Nikhil

Le bien connu JAXB

Il y a un maven plugin qui peut le faire pour vous à n'importe quelle phase de construction que vous voulez.

Vous pouvez faire cela dans les deux sens: xsd <-> Java

2
François Wauquier

À propos de la limitation JAXB, une solution pour avoir le même nom pour différents attributs consiste à ajouter des personnalisations jaxb en ligne au xsd:

+

. . déclarations contraignantes. .

ou personnalisations externes ...

Vous pouvez voir plus d'informations sur: http://jaxb.Java.net/tutorial/section_5_3-Overriding-Names.html

1
Nady