標準APIのJAXBを使うと、Javaのインスタンスの内容をXML形式で出力したり、逆にXMLファイルからJavaのインスタンスを生成することができます。Schema定義からJavaクラスを生成し、そのクラスを利用して実行時にJavaインスタンスとXML文書のマッピングをする機能が提供されました。その後のバージョンで、Javaクラス定義*1からJavaインスタンスとXML文書のマッピングをする機能が提供されました。Schema定義からJavaクラスを生成するものとなっています。今回、Javaクラス定義からXML文書とマッピングするために必要な流れを、一歩一歩試しながら理解したいと思います。Schemaを生成して内容を見ていきます。7最初の一歩:素のクラスまず、Javaクラスを定義します。{}これを次のディレクトリ構成に置きます。Schemaを生成するときは、JDKに含まれるコマンドschemagenを実行します。Schema上には型定義(complexType型で名前がweather)が生成されています。型名は、クラス名を小文字にしたものがデフォルトです。Schemaでは、極力名前空間を使うのがよいとされているので、生成されるSchemaに名前空間が含まれるように、JAXBのアノテーションを付与します。クラスに指定する方法もありますが、一般にはパッケージ名に対比させることが多いので、JavaのパッケージにJAXBのアノテーション@XmlSchemaを付けます。パッケージにアノテーションを付けるために、package-info.javaを作成します。jp.gr.java_conf.torutk.weather;名前空間を指定するため、namespace属性を指定するとともに、カメレオンスキーマはよくないとされているので、名前空間tnsを指定しています。名前空間は、javaのパッケージ名(DNSの逆順)をURI式に表現したものを使用しています。javaのパッケージ名にはハイフン('-')が使えないため、規約に従いハイフンをアンダースコアに置き換えていますので、URI式に表現するときはもとのハイフンに戻しています。このpackage-info.javaを含むディレクトリ構成は以下になります。Schemaを生成します。Schemaには、型宣言は生成されていますが、要素宣言はまだ生成されていません。XMLルート要素の指定ルート要素になるクラスにJAXBのアノテーション@XmlRootElementを付けます。{}先ほどと同じ指定でschemagenコマンドを実行します。指定が生成されました。要素名はクラス名を小文字にしたものとなっています。*3デフォルトでは、型がグローバル定義となっています。*4Weatherクラスのフィールド定義Weatherクラスは今まで空っぽでしたが、フィールドを追加します。ここでは、Measureクラスのリストをフィールドに定義します。Weather(気象データ)がMeasure(計測値)を複数保持するというデータ構造です。{}先ほど同様schemagenコマンドを実行します。生成されたschema1.xsdは先ほどと変わりません。XMLに出力するフィールドは、JAXBアノテーションで指定する必要があります。アノテーションは、フィールドを、子要素とするか属性とするかで、@XmlElementあるいは@XmlAttributeを指定します。measures;}これを先と同じくschemagenコマンドで実行すると、以下のclasses/schema1.xsdが生成されます。&lt;/xs:complexType&gt;&lt;/xs:schema&gt;JavaのList<Measure>が、XMLではmeasures要素の繰り返しに展開されています。java.util.ListはJAXBが標準で対応しています。ちなみに、java.util.Mapにしたところ、schemagenコマンドがエラーとなりました。interfaces.XML文書としてリストを束ねる要素があった方がいい?上述のListの場合、XML文書のイメージは次のようになります。.../&gt;&lt;/weather&gt;リストの場合、XML的には次のようになっていた方が気持ちがいいです。&lt;/measures&gt;&lt;/weather&gt;そのためには、Listのフィールドにアノテーション@XmlElementWrapperを追加します。measures;}schemagenコマンドで生成したclasses/schema1.xsdは次のようになります。先ほどまでは、空のクラスであったMeasureに、フィールドを追加します。JAXBアノテーションは付けないでおきます。dateTime;}schemagenコマンドを実行して生成されたclasses/schema1.xsdは、先ほどと変わりません。なんらかのJAXBアノテーションを付ける必要があります。Measure.javaにJAXBアノテーションを追加するここで、各フィールドを属性として生成したいので、@XmlAttributeを指定します。Schemaとしてclasses/schema1.xsdが生成されます。&lt;/xs:complexType&gt;&lt;/xs:schema&gt;JavaインスタンスからXML文書への出力では、実際にJavaプログラムでWeatherインスタンスを生成し、その内容をXML文書に出力してみます。Weather.javaとMeasure.javaは、フィールド定義しかないので、コンストラクタとアクセッサメソッドを追加します。}}JAXB対象のクラスは、引数なしのデフォルトコンストラクタが必要です。publicでなくてもよいので、他のパッケージから使用させない場合にも対応できます。XMLへの出力(SaveXml.java)標準出力にXML形式テキストを出力する簡単なサンプルです。}}コンパイルはできるが実行時にエラーが・・・コンパイルします。jp/gr/java_conf/torutk/weather/SaveXml.javawork$実行します。エラーメッセージによると、ObjectFactoryクラスかjaxb.indexをパッケージに含めないとだめとあります。SchemaからJAXBのxjcコマンドを使ってJavaクラスを生成するときに作られるものですから、今回は、jaxb.indexを作成して対応します。jaxb.indexファイルをパッケージに1つ作成するjaxb.indexはテキストファイルで、JAXBでマーシャリング対象となるクラス名を列挙したものです。今回は2つのクラスWeatherとMeasureがマーシャリング対象なので、この2つを記述します。WeatherMeasureクラス名は、パッケージ名を書かず、.classも付けません。これを実行時のクラスパス上、対象パッケージの場所におきます。jaxb.indexもう一度プログラムを実行します。&lt;/measures&gt;&lt;/weather&gt;work$出来ました、と言いたいところですが、名前空間が消えてしまっています。これは今後の宿題として、次はXML文書からの読み込みです。以下を参考にしました。*1:JAXBのアノテーションを付与ししたもの*2:クラスに@XmlType(name="Hoge")とアノテーションを付けると名前を変えることができます。Schema上の型定義がグローバルではなくローカルとなります。*3:@XmlRootElement(name="weatherinfo")とアノテーションで指定することもできます。*4:型を要素のローカル定義とする場合、クラスのアノテーションに@XmlType(name="")とします。*5:フィールドにアノテーションする以外にも、方法はありますが、ここでは割愛します。コメントを書くスパム対策のためのダミーです。