Generare classi Java da file .XSD ...?


127

Ho un gigantesco file di schema SDK .XSD di QuickBooks che definisce le richieste / risposte XML che posso inviare / ricevere da QuickBooks.

Mi piacerebbe essere in grado di generare facilmente classi Java da questi file .XSD, che potrei quindi utilizzare per eseguire il marshalling di oggetti XML in Java e oggetti Java in XML.

C'è un modo semplice per farlo ...?

Idealmente, non richiederebbe alcuna libreria esterna alla distribuzione Java di base in fase di esecuzione. Ma sono flessibile ...


6
Se vuoi la generazione manuale, inserisci il file .xsd nel tuo progetto eclipse, fai clic con il pulsante destro del mouse sul file, quindi fai clic su "genera"
Junchen Liu

Risposte:


121

JAXB fa ESATTAMENTE quello che vuoi. È integrato in JRE / JDK a partire da 1.6


7
Sfortunatamente, questa funzionalità non sarà più disponibile a partire da Java 9. Questo perché le classi coinvolte (in particolare le classi com.sun.tools.xjc. *) Non saranno più disponibili tramite JDK.
Marco,

4
Non penso che la rimozione di questo dal JDK dovrebbe essere un problema, perché il progetto java.net (collegato nella risposta) probabilmente rimarrà.
Stmoebius,

1
Come spiegato qui , è possibile aggiungere le dipendenze in Java 9 da un argomento della riga di comando o aggiungere manualmente la dipendenza.
Matthias Ronge l'

118

Per espandere i commenti "usa JAXB" sopra,

In Windows "%java_home%\bin\xjc" -p [your namespace] [xsd_file].xsd

per esempio, "%java_home%\bin\xjc" -p com.mycompany.quickbooks.obj quickbooks.xsd

Aspetta un po ', e se avessi un file XSD ben formato, otterrai alcune classi Java ben formate


3
Grazie mille! Per generare classi di livello superiore anziché incapsulato, consultare: stackoverflow.com/questions/13175224/… . E se porta a conflitti di nomi di classe, vedi: stackoverflow.com/questions/13414407/…
domani

38

Se vuoi iniziare a codificare Java in XML e XML in Java in meno di 5 minuti, prova la serializzazione XML semplice. Non perdere ore a imparare l'API JAXB http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php

Tuttavia, se sei davvero appassionato di apprendimento di JAXB, ecco un eccellente tutorial http://blogs.oracle.com/teera/entry/jaxb_for_simple_java_xml

Contenuto del tutorial:

JAXB per una semplice serializzazione Java-XML

Esistono diversi modi per eseguire la serializzazione XML in Java. Se si desidera un controllo accurato sull'analisi e sulla serializzazione, è possibile scegliere SAX, DOM o Stax per prestazioni migliori. Tuttavia, ciò che spesso voglio fare è una semplice mappatura tra POJO e XML. Tuttavia, la creazione di classi Java per eseguire manualmente l'analisi degli eventi XML non è banale. Recentemente ho scoperto che JAXB è una mappatura o serializzazione Java-XML rapida e conveniente.

JAXB contiene molte funzioni utili, puoi controllare l'implementazione di riferimento qui. Il Blog di Kohsuke è anche una buona risorsa per saperne di più su JAXB. Per questo post di blog, ti mostrerò come eseguire una semplice serializzazione Java-XML con JAXB.

POJO a XML

Diciamo che ho un oggetto Java Item. Voglio serializzare un oggetto Item in formato XML. Quello che devo fare prima è annotare questo POJO con alcune annotazioni XML dal pacchetto javax.xml.bind.annotation. *. Vedi il codice 1 per Item.java

Dal codice

  • @XmlRootElement(name="Item") indica che voglio essere l'elemento radice.
  • @XmlType(propOrder = {"name", "price"}) indica l'ordine in cui voglio che l'elemento sia organizzato nell'output XML.
  • @XmlAttribute(name="id", ...) indica che id è un attributo all'elemento root.
  • @XmlElement(....) indica che voglio che il prezzo e il nome siano elementi all'interno dell'articolo.

Il mio Item.javaè pronto. Posso quindi andare avanti e creare lo script JAXB per il marshalling 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"));

Per l'elenco completo dei codici, vedere l'elenco dei codici 2 main.java. item.xmlViene creato il file di output dell'elenco codici 3 . Sembra così:

<?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 vero? In alternativa, puoi canalizzare l'XML di output come stringa di testo, Stream, Writer, ContentHandler, ecc. Semplicemente cambiando il parametro del metodo marshal (...) come

...
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 a POJO

Invertire il processo. Supponiamo che ora ho un pezzo di dati stringa XML e voglio trasformarlo in oggetto Item.java. Assomigliano a dati XML (elenco di codici 3)

<?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>

Posso quindi riattivare questo codice XML sull'oggetto Item di

...
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;
...

Per l'elenco completo dei codici, vedere l'elenco dei codici 2 (main.java). Il sorgente XML può venire in molte forme sia da Stream che da file. L'unica differenza, ancora una volta, è il parametro del metodo:

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

Convalida con schema XML

L'ultima cosa che voglio menzionare qui è la convalida dell'XML di input con lo schema prima di smascherare l'oggetto Java. Creo un file di schema XML chiamato item.xsd. Per l'elenco completo dei codici, vedere l'elenco dei codici 4 (Item.xsd). Ora quello che devo fare è registrare questo schema per la convalida.

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

Quando provo a ripristinare i dati XML su POJO, se l'XML di input non è conforme allo schema, verrà rilevata un'eccezione. Per l'elenco completo dei codici, vedere l'elenco dei codici 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'.]

Qui cambio l'attributo 'id' in stringa anziché in intero.

Se l'input XML è valido contro lo schema, i dati XML verranno smascherati correttamente sull'oggetto Item.java.


1
Sembra molto promettente, e molto più semplice e piacevole con cui lavorare per quello di cui ho bisogno di qualcosa di grande e complicato come JAXB. Sfortunatamente, non vedo alcun modo per convertire i miei file .XSD esistenti in .class, che è davvero ciò di cui ho bisogno per iniziare. C'è un modo per fare questo?
Keith Palmer Jr.,

7
Sfortunatamente il blog con il tutorial JAXB non è in linea.
Luis C.

possiamo farlo facilmente usando jaxb2-maven-plugin, controlla questo tutorial journaldev.com/1312/…
Pankaj

che cosa è complicato di ""% java_home% \ bin \ xjc "-p [il tuo spazio dei nomi] [xsd_file] .xsd"?
Gorefest,

30

Utilizzando Eclipse IDE: -

  1. copia xsd in un progetto nuovo / esistente.
  2. Assicurati di avere JAR richiesti da JAXB nel tuo percorso di classe. Puoi scaricarne uno qui .
  3. Fare clic con il tasto destro sul file XSD -> Genera -> Classi JAXB.

17

il modo più semplice è usare la riga di comando. Digita semplicemente la directory del tuo file .xsd:

xjc myFile.xsd.

Quindi, il java genererà tutti i Pojo.


14

Maven può essere utilizzato allo scopo, è necessario aggiungere alcune dipendenze e pulire semplicemente l'applicazione. Tutte le classi verranno create automaticamente nella cartella di destinazione.

Basta copiarli dalla destinazione al luogo desiderato, ecco pom.xml che ho usato per creare classificati dai file 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>

Posiziona i tuoi file xsd in "src / main / webapp / schemas /" e Maven li troverà al momento della compilazione.

Spero che questo ti possa aiutare, maggiori informazioni sono disponibili all'indirizzo http://www.beingjavaguys.com/2013/04/create-spring-web-services-using-maven.html

Spero che possa aiutare :)


1
Funziona davvero con la directory delle risorse? (src / main / risorse / schemi), perché continuo a ottenere questo:No XSD files found. Please check your plugin configuration.
zygimantus,


7

Bene la migliore opzione è %java_home%\bin\xjc -p [your namespace] [xsd_file].xsd.

Ho anche una domanda se abbiamo un'opzione per fare il reverse engineering qui. se sì, possiamo generare xsd dalla classe pojo?


xjc è disponibile solo in java6
sree

7

Se non ti dispiace usare una libreria esterna, ho usato Castor per farlo in passato.


Se generi codice con Castor, quelle classi generate dipendono ancora da Caster dopo il fatto? O potrei spostare quelle classi su una macchina senza le librerie di Castor, e funzionerebbero ancora?
Keith Palmer Jr.,

No, le classi generate non dipendono dalle librerie di Castor.
Dave,

Ci sono dei buoni tutorial su come usare Castor per fare questo? Sembra molto promettente ... ma Java, per non dire altro, non è il mio linguaggio più forte. Non sono sicuro di quali file / pacchetti Castor ho bisogno di scaricare e come fare effettivamente la generazione del codice ... qualche esempio per principianti passo-passo in giro?
Keith Palmer Jr.,


2
Sembra che la macchina per colata continua sia morta da molto tempo ... I collegamenti di documenti sono tutti 404.
Pawel Veselov

5

Limitazione JAXB.

Ho lavorato su JAXB, secondo la mia opinione è un bel modo di gestire i dati tra oggetti XML e Java. I lati positivi sono le sue comprovate e migliori prestazioni e controllo sui dati durante il runtime. Con un buon uso di strumenti o script integrati, eliminerai molti sforzi di programmazione.

Ho scoperto che la parte di configurazione non è un compito immediato e ho passato ore a ottenere la configurazione dell'ambiente di sviluppo.

Tuttavia, ho lasciato cadere questa soluzione a causa di una sciocca limitazione che ho dovuto affrontare. La mia definizione di schema XML (XSD) ha un attributo / elemento con nome "valore" e che devo usare XSD così com'è. Questo vincolo molto limitato ha costretto il mio passo di associazione XJC fallito con un errore "Proprietà" Valore "già utilizzato."

Ciò è dovuto all'implementazione di JAXB, il processo di associazione tenta di creare oggetti Java da XSD aggiungendo pochi attributi a ciascuna classe e uno di questi è un attributo valore. Quando ha elaborato il mio XSD si è lamentato che esiste già una proprietà con quel nome.


4

XJC di JAXB non è una possibile risposta a questo? Sto cercando di ottenere la stessa cosa. Sempre nella fase "provante" però. È venuto attraverso XJC, quindi ho pensato di condividere.



Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.