私は、QuickBooksから送受信できるXML要求/応答を定義する巨大なQuickBooks SDK .XSDスキーマファイルを持っています。
これらの.XSDファイルからJavaクラスを簡単に生成できるようにしたいと思います。これを使用して、XMLをJavaオブジェクトに、JavaオブジェクトをXMLにマーシャリングできます。
これを行う簡単な方法はありますか...?
理想的には、実行時に基本的なJavaディストリビューションの外部にライブラリを必要としません。しかし、私は柔軟です...
私は、QuickBooksから送受信できるXML要求/応答を定義する巨大なQuickBooks SDK .XSDスキーマファイルを持っています。
これらの.XSDファイルからJavaクラスを簡単に生成できるようにしたいと思います。これを使用して、XMLをJavaオブジェクトに、JavaオブジェクトをXMLにマーシャリングできます。
これを行う簡単な方法はありますか...?
理想的には、実行時に基本的なJavaディストリビューションの外部にライブラリを必要としません。しかし、私は柔軟です...
回答:
JAXBはまさにあなたが望むものを実行します。JRE / JDKに1.6以降で組み込まれています
上記の「use JAXB」コメントを拡張するには、
Windowsの場合
"%java_home%\bin\xjc" -p [your namespace] [xsd_file].xsd
例えば、
"%java_home%\bin\xjc" -p com.mycompany.quickbooks.obj quickbooks.xsd
少し待ってください。整形式のXSDファイルがある場合は、整形式のJavaクラスがいくつか得られます。
JavaからXMLおよびXMLからJavaへのコーディングを5分未満で開始したい場合は、シンプルなXMLシリアル化を試してください。JAXB API http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.phpの学習に何時間も費やさないで ください
ただし、JAXBの学習に本当に熱心な場合は、次の優れたチュートリアルをご覧ください。 http://blogs.oracle.com/teera/entry/jaxb_for_simple_java_xml
チュートリアルの内容:
単純なJava-XMLシリアライゼーション用のJAXB
JavaでXMLシリアル化を行う方法はいくつかあります。解析とシリアル化をきめ細かく制御したい場合は、SAX、DOM、またはStaxを使用してパフォーマンスを向上させることができます。それでも、私がよくやりたいのは、POJOとXMLの間の単純なマッピングです。ただし、XMLイベント解析を手動で実行するJavaクラスを作成するのは簡単ではありません。私は最近、JAXBが迅速かつ便利なJava-XMLマッピングまたはシリアライゼーションであることを発見しました。
JAXBには多くの便利な機能が含まれています。ここでリファレンス実装を確認できます。 Kohsukeのブログは、JAXBについてさらに学ぶための優れたリソースでもあります。このブログエントリでは、JAXBを使用して簡単なJava-XMLシリアル化を行う方法を紹介します。
POJOからXML
私がItem Javaオブジェクトを持っているとしましょう。ItemオブジェクトをXML形式にシリアル化したいのですが。最初に行う必要があるのは、このPOJOにjavax.xml.bind.annotation。*パッケージからのいくつかのXMLアノテーションを付けることです。Item.javaのコードリスト1を参照してください
コードから
@XmlRootElement(name="Item") ルート要素になりたいことを示します。@XmlType(propOrder = {"name", "price"}) 要素をXML出力に配置する順序を示します。@XmlAttribute(name="id", ...) idがルート要素の属性であることを示します。@XmlElement(....) 価格と名前をアイテム内の要素にしたいことを示します。私Item.javaは準備ができています。次に、アイテムをマーシャリングするためのJAXBスクリプトを作成します。
//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"));
完全なコードリストについては、コードリスト2を参照してくださいmain.java。出力コードリスト3 item.xmlファイルが作成されます。次のようになります。
<?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>
簡単でしょう?または、次のようにmarshal(...)メソッドのパラメーターを変更するだけで、出力XMLをテキスト文字列、ストリーム、ライター、ContentHandlerなどとしてチャネリングできます。
...
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からPOJO
プロセスを逆にしましょう。XML文字列データがあり、それをItem.javaオブジェクトに変換したいとします。XMLデータ(コードリスト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>
次に、このxmlコードをItemオブジェクトに非整列化できます。
...
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;
...
完全なコードリストについては、コードリスト2(main.java)を参照してください。XMLソースは、ストリームとファイルの両方からさまざまな形式で提供されます。唯一の違いは、ここでもメソッドパラメータです。
...
unmarshaller.unmarshal(new File("Item.xml")); // reading from file
...
// inputStream is an instance of java.io.InputStream, reading from stream
unmarshaller.unmarshal(inputStream);
XMLスキーマによる検証
ここで最後に触れておきたいのは、Javaオブジェクトに非整列化する前に、入力XMLをスキーマで検証することです。item.xsdというXMLスキーマファイルを作成します。完全なコードリストについては、コードリスト4(Item.xsd)を参照してください。次に、このスキーマを検証用に登録する必要があります。
...
Schema schema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
.newSchema(new File("Item.xsd"));
unmarshaller.setSchema(schema); //register item.xsd shcema for validation
...
XMLデータをPOJOに非整列化しようとすると、入力XMLがスキーマに準拠していない場合、例外がキャッチされます。完全なコードリストについては、コードリスト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'.]
ここで、「id」属性を整数ではなく文字列に変更します。
XML入力がスキーマに対して有効な場合、XMLデータは正常にItem.javaオブジェクトに非整列化されます。
Mavenはこの目的に使用できます。依存関係をいくつか追加して、アプリケーションをクリーンアップする必要があります。ターゲットフォルダに自動的に作成されたすべてのクラスを取得します。
ターゲットから目的の場所にコピーするだけです。これは、xsdファイルからクラスを作成するために使用したpom.xmlです。
<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>
「src / main / webapp / schemas /」の下にxsdファイルを置くだけで、mavenはコンパイル時にそれらを見つけます。
これがお役に立てば幸いです。詳細については、http://www.beingjavaguys.com/2013/04/create-spring-web-services-using-maven.htmlをご覧ください。
それが役に立てば幸い:)
No XSD files found. Please check your plugin configuration.
XMLBeansがそれを行います。特に「scomp」コマンド。
編集:XMLBeansは廃止されました。詳細については、このStackoverflowの投稿を確認してください。
外部ライブラリを使用することを気にしない場合、私はこれまでCastorを使用してこれを行ってきました。
JAXBの制限。
私の意見では、XMLとJavaオブジェクトの間でデータを処理するための優れた方法であるJAXBに取り組みました。肯定的な面は、実績があり、実行時のパフォーマンスとデータの制御において優れています。構築されたツールまたはスクリプトを適切に使用することで、多くのコーディング作業が不要になります。
構成の部分は簡単な作業ではなく、開発環境のセットアップに何時間も費やしました。
しかし、私が直面したばかげた制限のため、私はこのソリューションを削除しました。私のXMLスキーマ定義(XSD)には、「値」という名前の属性/要素があり、XSDをそのまま使用する必要があります。このごくわずかな制約のために、バインディングプロセスXJCはエラー「プロパティ '値'はすでに使用されています」で失敗しました。
これはJAXB実装が原因です。バインディングプロセスは、各クラスにいくつかの属性を追加し、そのうちの1つを値属性として、XSDからJavaオブジェクトを作成しようとします。それが私のXSDを処理したとき、その名前のプロパティがすでにあると不平を言いました。
JAXB制限について言えば、異なる属性に同じ名前を使用する場合の解決策は、xsdにインラインjaxbカスタマイズを追加することです。
+
。。バインディング宣言。。
または外部のカスタマイズ...
詳細については、http://jaxb.java.net/tutorial/section_5_3-Overriding-Names.htmlをご覧ください。