先週は,JAXBを用いてXMLのスキーマからJavaのクラス生成ができることを紹介しました。そして,生成したクラスを使用してXMLドキュメントからJavaのオブジェクトを生成させました。

XMLのスキーマとJavaのクラスを対応させることをバインディング,XMLドキュメントからJavaのオブジェクトを生成させることをアンマーシャリングということも紹介しました。

今週はアンマーシャリングの逆,マーシャリングを行ってみます。つまり,JavaオブジェクトからXMLドキュメントを生成します。

先週使用した,複数の名前を表すスキーマを今週も使用しましょう。XML Schemaで表したスキーマを次に示します。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0"
    targetNamespace="http://xml.javainthebox.net" 
    xmlns:tns="http://xml.javainthebox.net"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
  <xs:element name="persons">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="tns:person" 
                    minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
 
  <xs:element name="person">
    <xs:complexType>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="age" type="xs:int"/>
      <xs:attribute name="sex" type="tns:sex"/>
    </xs:complexType>
  </xs:element>
 
  <xs:simpleType name="sex">
    <xs:restriction base="xs:string">
      <xs:enumeration value="MALE"/>
      <xs:enumeration value="FEMALE"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

スキーマの詳細な解説は行いませんが,何を表しているのかだけ簡単に説明しましょう。

スキーマが四つのパートに別れていることは,すぐにわかるはずです。1番目のバートがスキーマの定義,次がルートタグであるpersonsタグの定義です。personsタグにはpersonタグが複数含まれています。

3番目のパートが,personタグの定義です。personタグにはname,age,sexの三つのアトリビュートが存在します。

最後のパートがsexのアトリビュートに使用できる型の定義です。sexは性別なので,MALEかFEMALEのどちらかの値をとります。

まず,このスキーマからJavaのクラスをxjcコマンドを使って,作成します。

C:\jaxb>xjc persons.xsd
parsing a schema...
compiling a schema...
net\javainthebox\xml\ObjectFactory.java
net\javainthebox\xml\Person.java
net\javainthebox\xml\Persons.java
net\javainthebox\xml\Sex.java
net\javainthebox\xml\package-info.java

ファクトリクラスのObjectFactoryクラスとパッケージの定義を行うpackage-info.java以外はすべてスキーマで定義された型に対応しています。

ここまでが,先週のおさらいです。

今週は,これらのクラスを利用してXMLドキュメントを生成していきましょう。

先週紹介したように,XMLドキュメントからJavaのオブジェクトを生成するアンマーシャリングにはjavax.xml.bind.Unmarshallerインタフェースを使用します。

これと同じように,JavaオブジェクトからXMLドキュメントを生成するマーシャリングにはjavax.xml.bind.Marshallerインタフェースを使用します。

Marshallerはインタフェースなので,オブジェクトを得るにはファクトリが必要です。Unmarshallerインタフェースの場合と同じく,このファクトリクラスはjavax.xml.bind.JAXBContextクラスになります。

サンプルのソース MarshallerSample1.java

このサンプルはpersons.xsdで定義されたXMLドキュメントを読み込み,Personsオブジェクトを生成します。

public class MarshallerSample1 {
    public MarshallerSample1() {
        try {
            // 1. JAXBContextオブジェクトの生成
            // 引数はパッケージもしくはクラス
            JAXBContext context 
                = JAXBContext.newInstance("net.javainthebox.xml");
 
            // 2. Marsallerオブジェクトの取得
            Marshaller marshaller = context.createMarshaller();
 
            // 3. マーシャリングするオブジェクトを準備
            Persons persons = createPersons();
 
            // 4. マーシャリング出力先
            //    出力にはストリームを使用
            FileOutputStream stream 
                = new FileOutputStream("artists2.xml");
 
            // 5. マーシャリング
            marshaller.marshal(persons, stream);
        } catch (FileNotFoundException ex) {
            // 例外処理
            System.err.println("artists2.xml がオープンできません");
        } catch (JAXBException ex) {
            // 例外処理
            System.err.println("マーシャリングに失敗しました");
        }
    }

JAXBContextオブジェクトの生成には,先週も紹介したようにJAXBContextクラスのnewInstanceメソッドを使用します。

青字で示した部分がMarshallerオブジェクトを生成している部分です。Unmarshallerオブジェクトの場合はcreateUnmarshallerメソッド,Marshallerオブジェクトの場合はcreateMarshallerメソッドを使用します。

マーシャリングには,赤字で示したように,Marshallerインタフェースのmarshalメソッドをコールします。第1引数がマーシャリングするオブジェクト,第2引数がマーシャリングする出力先を示します。

ここでは,ストリームを使用しましたが,アンマーシャリングと同様,多用な出力先を選べます。

  • ストリーム/ライター
  • XSLTのリザルト
  • DOMのノード
  • SAXのコンテントハンドラー
  • StAXのXMLStreamWriter/XMLEventWriter

マーシャリングの対象となるオブジェクトを生成しているのがcreatePersonsメソッドです。

    private Persons createPersons() {
        Persons persons = new Persons();

        Person person = new Person();
        person.setName("Paul McCartney");
        person.setAge(66);
        person.setSex(Sex.MALE);
        persons.getPerson().add(person);

        person = new Person();
        person.setName("Mick Jagger");
        person.setAge(65);
        person.setSex(Sex.MALE);
        persons.getPerson().add(person);

        person = new Person();
        person.setName("Mary Hopkins");
        person.setAge(58);
        person.setSex(Sex.FEMALE);
        persons.getPerson().add(person);

        return persons;
    }

xjcで生成したPersonsクラス,Personクラスはごくごく普通のクラスです。newを使用して普通に生成し,セッターでフィールドに値をセットしていくだけです。

ソースができたので,コンパイルして実行してみましょう。xjcで生成されたクラスをコンパイルすることを忘れないでください。

正しく動作していれば,artists2.xmlファイルが生成できているはずです。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><persons xmlns="http://xml.javainthebox.net"><person sex="MALE" age="66" name="Paul McCartney"/><person sex="MALE" age="65" name="Mick Jagger"/><person sex="FEMALE" age="58" name="Mary Hopkins"/></persons>

整形されていないのでちょっと見にくいですが,意図したとおりのXMLファイルが生成されました。

この先は会員の登録が必要です。有料会員(月額プラン)は初月無料!

日経 xTECHには有料記事(有料会員向けまたは定期購読者向け)、無料記事(登録会員向け)、フリー記事(誰でも閲覧可能)があります。有料記事でも、登録会員向け配信期間は登録会員への登録が必要な場合があります。有料会員と登録会員に関するFAQはこちら