web-dev-qa-db-ger.com

Java Klassen aus .XSD-Dateien generieren ...?

Ich habe eine gigantische QuickBooks SDK .XSD-Schemadatei, die XML-Anforderungen/-Antworten definiert, die ich von QuickBooks senden/empfangen kann.

Ich möchte in der Lage sein, auf einfache Weise Java Klassen aus diesen .XSD-Dateien zu generieren, mit denen ich dann XML zu Java Objekte und = Java Objekte in XML.

Gibt es eine einfache Möglichkeit, dies zu tun ...?

Idealerweise würde es keine Bibliotheken außerhalb der Basis-Distribution Java zur Laufzeit benötigen. Aber ich bin flexibel ...

122

[~ # ~] jaxb [~ ​​# ~] macht genau das, was Sie wollen. Es ist ab 1.6 in das JRE/JDK integriert

119
basszero

Um die obigen "JAXB verwenden" -Kommentare zu erweitern,

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

z.B., "%Java_home%\bin\xjc" -p com.mycompany.quickbooks.obj quickbooks.xsd

Warten Sie etwas, und wenn Sie eine wohlgeformte XSD-Datei hatten, erhalten Sie einige wohlgeformte Java Klassen

116
Ed Norris

Wenn Sie in weniger als 5 Minuten mit dem Codieren von Java in XML und von XML in Java) beginnen möchten, versuchen Sie es mit der einfachen XML-Serialisierung. Verbringen Sie keine Stunden mit dem Erlernen von JAXB API http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php

Wenn Sie jedoch wirklich JAXB lernen möchten, finden Sie hier ein hervorragendes Tutorial http://blogs.Oracle.com/teera/entry/jaxb_for_simple_Java_xml

Inhalt des Tutorials:

JAXB für einfache Java-XML-Serialisierung

Es gibt verschiedene Möglichkeiten, XML-Serialisierung in Java durchzuführen. Wenn Sie die Analyse und Serialisierung genau steuern möchten, können Sie für eine bessere Leistung SAX, DOM oder Stax wählen. Was ich jedoch oft tun möchte, ist eine einfache Zuordnung zwischen POJOs und XML. Es ist jedoch nicht einfach, Java Klassen für die manuelle Analyse von XML-Ereignissen zu erstellen. Ich habe kürzlich festgestellt, dass JAXB eine schnelle und bequeme Java-XML-Zuordnung oder -Serialisierung ist.

JAXB enthält viele nützliche Funktionen. Hier können Sie die Referenzimplementierung überprüfen. Kohsukes Blog ist auch eine gute Quelle, um mehr über JAXB zu erfahren. In diesem Blogeintrag zeige ich Ihnen, wie Sie mit JAXB eine einfache Java-XML-Serialisierung durchführen.

POJO zu XML

Angenommen, ich habe ein Item Java object. Ich möchte ein Item-Objekt in das XML-Format serialisieren. Zuerst muss ich dieses POJO mit ein paar XML-Annotationen aus javax.xml versehen. bind.annotation. * package. Siehe Codeauflistung 1 für Item.Java

Aus dem Code

  • @XmlRootElement(name="Item") gibt an, dass ich das Root-Element sein möchte.
  • @XmlType(propOrder = {"name", "price"}) gibt die Reihenfolge an, in der das Element in der XML-Ausgabe angeordnet werden soll.
  • @XmlAttribute(name="id", ...) gibt an, dass id ein Attribut für das Stammelement ist.
  • @XmlElement(....) gibt an, dass Preis und Name in Item als Element verwendet werden sollen.

Mein Item.Java ist bereit. Ich kann dann ein JAXB-Skript für das Marshalling von Item erstellen.

//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"));

Eine vollständige Codeauflistung finden Sie unter Codeauflistung 2 main.Java. Die Ausgabe Code Listing 3 item.xml Datei wird erstellt. Es sieht aus wie das:

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

Einfach richtig? Alternativ können Sie das Ausgabe-XML als Text-String, Stream, Writer, ContentHandler usw. kanalisieren, indem Sie einfach den Parameter der Marshall-Methode (...) wie folgt ändern

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

Kehren wir den Prozess um. Angenommen, ich habe jetzt eine XML-Zeichenfolge und möchte sie in ein Item.Java-Objekt umwandeln. XML-Daten (Code Listing 3) sehen so aus

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

Ich kann diesen XML-Code dann für das Item-Objekt von demarkieren

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

Eine vollständige Codeauflistung finden Sie in Codeauflistung 2 (main.Java). Die XML-Quelle kann in vielen Formen sowohl aus Stream als auch aus Datei stammen. Der einzige Unterschied ist wiederum der Methodenparameter:

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

Validierung mit XML-Schema

Das Letzte, was ich hier erwähnen möchte, ist das Validieren von Eingabe-XML mit Schema vor dem Aufheben der Zuordnung zu Java object. Ich erstelle eine XML-Schemadatei mit dem Namen item.xsd. Eine vollständige Codeauflistung finden Sie in Codeauflistung 4 (Item Jetzt muss ich dieses Schema zur Validierung registrieren.

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

Wenn ich versuche, XML-Daten für POJO zu dekomprimieren, wird eine Ausnahme abgefangen, wenn die Eingabe-XML nicht dem Schema entspricht. Eine vollständige Codeauflistung finden Sie in Codeauflistung 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'.]

Hier ändere ich das 'id'-Attribut in string anstelle von integer.

Wenn die XML-Eingabe für das Schema gültig ist, wird die Zuordnung der XML-Daten zum Item.Java-Objekt erfolgreich aufgehoben.

37
Aries McRae

Verwenden der Eclipse-IDE: -

  1. kopieren Sie die xsd in ein neues/vorhandenes Projekt.
  2. Stellen Sie sicher, dass Sie JAXB-JARs in Ihrem Klassenpfad haben. Sie können eines herunterladen hier .
  3. Klicken Sie mit der rechten Maustaste auf die XSD-Datei -> Generieren -> JAXB-Klassen.
29
Kumar Sambhav

der einfachste Weg ist die Verwendung der Befehlszeile. Geben Sie einfach das Verzeichnis Ihrer .xsd-Datei ein:

xjc myFile.xsd.

Das Java generiert also alle Pojos.

16
Willian Crozeta

XMLBeans wird es tun. Insbesondere der Befehl "scomp".

BEARBEITEN: XMLBeans wurde im Ruhestand , überprüfen Sie dieser Stackoverflow-Beitrag für weitere Informationen.

14
TofuBeer

Maven kann für den Zweck verwendet werden, Sie müssen einige Abhängigkeiten hinzufügen und einfach Ihre Anwendung bereinigen. Sie erhalten alle Klassen automatisch in Ihrem Zielordner erstellt.

Kopieren Sie sie einfach vom Ziel an den gewünschten Ort. Hier ist die Datei pom.xml, die ich zum Erstellen von Klassen aus XSD-Dateien verwendet habe:

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

Platzieren Sie einfach Ihre xsd-Dateien unter "src/main/webapp/schemas /" und maven findet sie beim Kompilieren.

Ich hoffe, dies wird Ihnen helfen. Weitere Informationen finden Sie unter http://www.beingjavaguys.com/2013/04/create-spring-web-services-using-maven.html

Hoffe es wird helfen :)

12
neel4soft

Wenn es Ihnen nichts ausmacht, eine externe Bibliothek zu verwenden, habe ich Castor verwendet, um dies in der Vergangenheit zu tun.

7
Marc Novakowski

Nun, die beste Option ist %Java_home%\bin\xjc -p [your namespace] [xsd_file].xsd.

Ich habe auch eine Frage, ob wir hier die Möglichkeit haben, Reverse Engineering durchzuführen. Wenn ja, können wir xsd aus der Pojo-Klasse generieren?

7
sree

JAXB-Einschränkung.

Ich habe an JAXB gearbeitet, da es meiner Meinung nach eine gute Art ist, mit Daten zwischen XML und Java) - Objekten umzugehen. Mit einer guten Verwendung der erstellten Tools oder Skripte wird eine Menge Programmieraufwand wegfallen.

Ich fand, dass der Konfigurationsteil keine sofortige Aufgabe ist, und verbrachte Stunden damit, die Entwicklungsumgebung einzurichten.

Ich habe diese Lösung jedoch aufgrund einer dummen Einschränkung fallen lassen, mit der ich konfrontiert war. Meine XML-Schemadefinition (XSD) hat ein Attribut/Element mit dem Namen "value" und ich muss XSD so verwenden, wie es ist. Diese sehr kleine Einschränkung erzwang, dass mein Bindungsschritt XJC fehlschlug, und zwar mit der Fehlermeldung "Eigenschaft 'Wert' wurde bereits verwendet".

Dies ist auf die JAXB-Implementierung zurückzuführen, bei der der Bindungsprozess versucht, Java aus XSD-Objekten zu erstellen, indem jeder Klasse einige Attribute hinzugefügt werden, von denen eine ein Wertattribut ist beschwerte sich, dass es bereits eine Immobilie mit diesem Namen gibt.

5
RAm

Ist der XJC von JAXB nicht eine mögliche Antwort auf diese Frage? Ich versuche das Gleiche zu erreichen. Immer noch in der "Versuchsphase". Kam über XJC, dachte also über das Teilen nach.

4
Nikhil

Das bekannte [~ # ~] jaxb [~ ​​# ~]

Es gibt ein Maven-Plugin , das dies für Sie in jeder gewünschten Erstellungsphase erledigen kann.

Sie können dies auf beide Arten tun: xsd <-> Java

2

Apropos JAXB-Einschränkung: Eine Lösung, wenn derselbe Name für verschiedene Attribute verwendet wird, besteht darin, der xsd Inline-Jaxb-Anpassungen hinzuzufügen:

+

. . verbindliche Erklärungen. .

oder externe Anpassungen ...

Weitere Informationen finden Sie unter: http://jaxb.Java.net/tutorial/section_5_3-Overriding-Names.html

1
Nady