Hasilkan kelas Java dari file .XSD ...?

127

Saya memiliki file skema QuickBooks SDK .XSD yang sangat besar yang mendefinisikan permintaan / tanggapan XML yang dapat saya kirim / terima dari QuickBooks.

Saya ingin dapat dengan mudah menghasilkan kelas Java dari file .XSD ini, yang kemudian dapat saya gunakan untuk menyusun XML ke objek Java, dan objek Java ke XML.

Apakah ada cara mudah untuk melakukan ini ...?

Idealnya, itu tidak memerlukan perpustakaan eksternal ke distro Java dasar saat dijalankan. Tapi saya fleksibel ...

Keith Palmer Jr.
sumber
6
Jika Anda menginginkan pembuatan manual, tempatkan file .xsd di proyek gerhana Anda, klik kanan file itu, lalu tekan "hasilkan"
Junchen Liu

Jawaban:

121

JAXB melakukan apa yang Anda inginkan. Ini dibangun ke dalam JRE / JDK mulai dari 1,6

basszero
sumber
7
Sayangnya, fungsi ini tidak lagi tersedia pada Java 9. Ini karena kelas yang terlibat (khususnya, kelas com.sun.tools.xjc. *) Tidak lagi tersedia melalui JDK.
Marco
4
Saya tidak berpikir penghapusan ini dari JDK harus menjadi masalah, karena proyek java.net (tertaut dalam jawabannya) mungkin akan tetap ada.
stmoebius
1
Seperti yang dijelaskan di sini , Anda dapat menambahkan dependensi di Java 9 dengan argumen baris perintah, atau menambahkan dependensi secara manual.
Matthias Ronge
118

Untuk memperluas "gunakan JAXB" komentar di atas,

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

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

Tunggu sebentar, dan jika Anda memiliki file XSD yang baik, Anda akan mendapatkan beberapa kelas Java yang baik

Ed Norris
sumber
3
Terima kasih banyak! Untuk menghasilkan kelas tingkat atas daripada enkapsulasi, lihat: stackoverflow.com/questions/13175224/… . Dan jika itu mengarah ke konflik nama kelas, lihat: stackoverflow.com/questions/13414407/…
besok
38

Jika Anda ingin mulai mengkode Java ke XML dan XML ke Java dalam waktu kurang dari 5 menit, coba Serialisasi Sederhana XML. Jangan menghabiskan waktu berjam-jam mempelajari JAXB API http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php

Namun, jika Anda benar-benar tertarik mempelajari JAXB, berikut ini adalah tutorial yang bagus http://blogs.oracle.com/teera/entry/jaxb_for_simple_java_xml

Isi tutorial:

JAXB untuk serialisasi Java-XML sederhana

Ada sejumlah cara untuk melakukan serialisasi XML di Jawa. Jika Anda ingin kontrol halus atas parsing dan serialisasi, Anda bisa menggunakan SAX, DOM, atau Stax untuk kinerja yang lebih baik. Namun, yang sering ingin saya lakukan adalah pemetaan sederhana antara POJO dan XML. Namun, membuat kelas Java untuk melakukan parsing acara XML secara manual bukanlah hal sepele. Baru-baru ini saya menemukan JAXB sebagai pemetaan atau serialisasi Java-XML yang cepat dan nyaman.

JAXB berisi banyak fitur yang bermanfaat, Anda dapat melihat implementasi referensi di sini. Blog Kohsuke juga merupakan sumber yang bagus untuk mempelajari lebih lanjut tentang JAXB. Untuk entri blog ini, saya akan menunjukkan kepada Anda bagaimana melakukan serialisasi Java-XML sederhana dengan JAXB.

POJO ke XML

Katakanlah saya memiliki objek Item Java. Saya ingin membuat serial objek untuk format XML. Apa yang harus saya lakukan pertama adalah untuk membubuhi keterangan POJO ini dengan beberapa penjelasan XML dari javax.xml.bind.annotation. * Paket. Lihat daftar kode 1 untuk Item.java

Dari kode

  • @XmlRootElement(name="Item") menunjukkan bahwa saya ingin menjadi elemen root.
  • @XmlType(propOrder = {"name", "price"}) menunjukkan urutan bahwa saya ingin elemen diatur dalam output XML.
  • @XmlAttribute(name="id", ...) menunjukkan bahwa id adalah atribut untuk elemen root.
  • @XmlElement(....) menunjukkan bahwa saya ingin harga dan nama menjadi elemen dalam Item.

Saya Item.javasiap Saya kemudian dapat melanjutkan dan membuat skrip JAXB untuk mengatur 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"));

Untuk Daftar Kode lengkap silakan lihat Daftar Kode 2 main.java. File Daftar Kode output 3 item.xmldibuat. Ini terlihat seperti ini:

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

Mudah bukan? Anda juga dapat menyalurkan output XML sebagai String teks, Stream, Penulis, ContentHandler, dll dengan hanya mengubah parameter metode marshal (...) seperti

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

Mari kita balikkan prosesnya. Asumsikan bahwa saya sekarang memiliki sepotong data string XML dan saya ingin mengubahnya menjadi objek Item.java. Data XML (Daftar kode 3) terlihat seperti

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

Saya kemudian dapat menghapus kode xml ini ke objek Item oleh

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

Untuk Daftar Kode lengkap silakan lihat Daftar Kode 2 (main.java). Sumber XML dapat datang dalam berbagai bentuk baik dari Stream dan file. Satu-satunya perbedaan, sekali lagi, adalah parameter metode:

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

Validasi dengan Skema XML

Hal terakhir yang ingin saya sebutkan di sini adalah memvalidasi input XML dengan skema sebelum membatalkan ke objek Java. Saya membuat file skema XML yang disebut item.xsd. Untuk Daftar Kode lengkap silakan lihat Daftar Kode 4 (Item.xsd). Sekarang yang harus saya lakukan adalah mendaftarkan skema ini untuk validasi.

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

Ketika saya mencoba untuk menghapus data XML ke POJO, jika input XML tidak sesuai dengan skema, pengecualian akan ditangkap. Untuk Daftar Kode lengkap, lihat Daftar Kode 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'.]

Di sini saya mengubah atribut 'id' menjadi string dan bukan bilangan bulat.

Jika input XML valid terhadap skema, data XML tidak akan berhasil untuk objek Item.java berhasil.

Aries McRae
sumber
1
Ini terlihat sangat menjanjikan, dan jauh lebih sederhana dan lebih baik untuk digunakan untuk apa yang saya butuhkan daripada sesuatu yang besar dan rumit seperti JAXB. Sayangnya, saya tidak melihat cara untuk mengkonversi file .XSD ke .class yang ada, yang benar-benar perlu saya mulai. Apakah ada cara untuk melakukan ini?
Keith Palmer Jr.
7
Sayangnya blog dengan Tutorial JAXB sedang offline.
Luis C.
kita bisa melakukannya dengan mudah menggunakan jaxb2-maven-plugin, periksa tutorial ini journaldev.com/1312/…
Pankaj
apa yang rumit tentang ""% java_home% \ bin \ xjc "-p [namespace Anda] [xsd_file] .xsd"?
gorefest
30

Menggunakan Eclipse IDE: -

  1. salin xsd ke proyek baru / yang sudah ada.
  2. Pastikan Anda memiliki JAXB yang diperlukan JAR di classpath Anda. Anda dapat mengunduhnya di sini .
  3. Klik kanan pada file XSD -> Hasilkan -> kelas JAXB.
Kumar Sambhav
sumber
17

cara termudah adalah menggunakan baris perintah. Cukup ketikkan direktori file .xsd Anda:

xjc myFile.xsd.

Jadi, java akan menghasilkan semua Pojo.

Crozeta
sumber
14

Maven dapat digunakan untuk tujuan itu, Anda perlu menambahkan beberapa dependensi dan hanya membersihkan aplikasi Anda. Anda akan membuat semua kelas dibuat secara otomatis di folder target Anda.

Cukup salin dari target ke tempat yang diinginkan, berikut ini pom.xml yang telah saya gunakan untuk membuat file dari 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>

Cukup tempatkan file xsd Anda di bawah "src / main / webapp / schemas /" dan maven akan menemukannya pada waktu kompilasi.

Semoga ini bisa membantu Anda, informasi lebih lanjut dapat ditemukan di http://www.beingjavaguys.com/2013/04/create-spring-web-services-using-maven.html

Semoga ini akan membantu :)

neel4soft
sumber
1
Apakah ini benar-benar berfungsi dengan direktori sumber daya? (src / main / resources / schemas), karena saya terus mendapatkan ini:No XSD files found. Please check your plugin configuration.
zygimantus
7

Pilihan terbaik adalah %java_home%\bin\xjc -p [your namespace] [xsd_file].xsd.

Saya juga punya pertanyaan jika kami memiliki opsi untuk melakukan reverse engineering di sini. jika ya dapatkah kita menghasilkan xsd dari kelas pojo?

sree
sumber
xjc hanya tersedia dalam java6
sree
7

Jika Anda tidak keberatan menggunakan perpustakaan eksternal, saya telah menggunakan Castor untuk melakukan ini di masa lalu.

Marc Novakowski
sumber
Jika Anda membuat kode dengan Castor, apakah kelas yang dihasilkan masih bergantung pada Caster setelah faktanya? Atau bisakah aku memindahkan kelas-kelas itu ke mesin tanpa perpustakaan Castor, dan mereka masih bekerja?
Keith Palmer Jr.
Tidak, kelas yang dihasilkan tidak tergantung pada pustaka Castor.
dave
Apakah ada tutorial bagus tentang cara menggunakan Castor untuk melakukan ini? Kelihatannya sangat menjanjikan ... tetapi Jawa, untuk sedikitnya, bukan bahasa terkuat saya. Saya tidak yakin apa file / paket Castor yang perlu saya unduh dan bagaimana cara benar-benar melakukan pembuatan kode ... contoh pemula apa saja selangkah demi selangkah?
Keith Palmer Jr.
Lihat halaman ini untuk dokumentasi tentang cara menggunakan kelas Castor SourceGenerator: castor.org/sourcegen.html
Marc Novakowski
2
Tampaknya kastor sudah lama mati ... Tautan dokumen semuanya 404.
Pawel Veselov
5

Batasan JAXB.

Saya bekerja di JAXB, sesuai pendapat saya ini cara yang bagus untuk berurusan dengan data antara objek XML dan Java. Sisi positifnya terbukti dan lebih baik dalam kinerja dan kontrol atas data selama runtime. Dengan penggunaan alat atau skrip yang dibangun dengan baik, ini akan menghilangkan banyak upaya pengkodean.

Saya menemukan bagian konfigurasi bukanlah tugas langsung, dan menghabiskan berjam-jam dalam mendapatkan pengaturan lingkungan pengembangan.

Namun saya menjatuhkan solusi ini karena keterbatasan konyol yang saya hadapi. Definisi Skema XML (XSD) saya memiliki atribut / elemen dengan nama "nilai" dan saya harus menggunakan XSD apa adanya. Kendala yang sangat kecil ini memaksa langkah mengikat saya XJC gagal dengan Kesalahan "Nilai Properti 'sudah digunakan."

Ini karena implementasi JAXB, proses pengikatan mencoba membuat objek Java dari XSD dengan menambahkan beberapa atribut ke setiap kelas dan salah satunya menjadi atribut nilai. Ketika memproses XSD saya, ia mengeluh bahwa sudah ada properti dengan nama itu.

RAm
sumber
4

Bukankah XJC JAXB adalah jawaban yang mungkin untuk ini? Saya berusaha mencapai hal yang sama. Masih dalam fase "mencoba". Datang di XJC, jadi terpikir untuk berbagi.

Niks
sumber
2

Yang terkenal JAXB yang

Ada plugin pakar yang bisa melakukan ini untuk Anda pada tahap membangun yang Anda inginkan.

Anda bisa melakukan hal ini dengan dua cara: xsd <-> Java

François Wauquier
sumber