JAXBメモ

作成 2003/7/28

はじめてのJAXB

巷で話題?のJAXBに、ちょっとだけさわってみました。ほんとにちょっとだけ。

JAXBとは?

JAXB(Java Architecture for XML Binding)とは、JavaとXMLのバインディング技術です。XMLのスキーマ(XMLスキーマ、DTD、RELAX NG、etc...)からJavaコードを作成することができます。作成したJavaコードにXMLファイルからデータを読み込んだり(マーシャリング)、逆にXMLを書き出したり(アンマーシャリング)できます。

実験環境

準備

JAXBを使うにはJAXBのライブラリ(JARとか)をダウンロードする必要があります。JAXBの実装はいろいろある?ようですが、ここでは、Java Web Services Developer Packを利用します。以下のページからJava Web Services Developer Packをダウンロード、インストールします。

http://java.sun.com/xml/download.html

Windowsの場合はインストーラで、JAXBの他にいろいろインストールされます。JAXBしたいだけなのに。。。まあ、そのうち、他のものも使うこともあるか。。。。インストールしたディレクトリ(C:\jwsdp-1.2など)のjaxb/sampleディレクトリにサンプルがあります。sample以下の各ディレクトリでantコマンドを実行すれば、なにやらいろいろ出来ていろいろ実行できるのが確認できます。

Javaコードの作成

スキーマからJavaコードの作成にはAntを利用します。実行するタスクは、JAXBで定義されているxjcタスク(XJCTask)を利用します。タスクのマニュアルはjaxb/docs/ant.htmlです。簡単なXMLスキーマを作って、xjcタスクを実行してみました。

hoge.xsd(XMLスキーマ)

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="man" type="manType"/>

<xsd:complexType name="manType">
  <xsd:sequence>
    <xsd:element name="name" type="xsd:string"/>
    <xsd:element name="age" type="xsd:decimal"/>
  </xsd:sequence>
</xsd:complexType>

</xsd:schema>

build.xml(Antビルドファイル。以下抜粋)

    <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
        <classpath refid="classpath" />
    </taskdef>

    <target name="xsd2java">
        <xjc schema="hoge.xsd" target="gensrc" package="hoge.xsd"/>
    </target>

Antビルドファイルでは、xjcタスクをtaskdefで定義して、xjcタスクを実行します。classpathでクラスパスにあれこれ通します(サンプルのビルドファイルをちょっとだけ改造したものです)。xsd2javaターゲット(これは自分で適当につけたtarget名)を実行すると、gensrc以下にJavaファイルが作成されます。

実行結果

C:\eclipse211\projects\etc\jaxb1>ant dtd2java
Buildfile: build.xml

dtd2java:
      [xjc] Compiling file:/C:/eclipse211/projects/etc/jaxb1/hoge.dtd
      [xjc] Writing output to C:\eclipse211\projects\etc\jaxb1\gensrc

BUILD SUCCESSFUL
Total time: 5 seconds
C:\eclipse211\projects\etc\jaxb1>ant xsd2java
Buildfile: build.xml

xsd2java:
      [xjc] Compiling file:/C:/eclipse211/projects/etc/jaxb1/hoge.xsd
      [xjc] Writing output to C:\eclipse211\projects\etc\jaxb1\gensrc

BUILD SUCCESSFUL
Total time: 4 seconds

マーシャリングとアンマーシャリング(XMLスキーマ編)

以下は、上で作ったXMLスキーマの形式にあうXMLファイルです。

hoge.xml

<?xml version="1.0"?>
<man>
    <name>miya</name>
    <age>10</age>
</man>

このhoge.xmlを読み込み、書き出しするJavaクラスが以下です。読み込んだあと、値を出力し、さらに値を代入して、標準出力にXMLを書き出しています。

XSLMain.java

import hoge.xsd.Man;

import java.io.FileInputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class XSDMain {

    public static void main(String[] args) throws Exception {

        JAXBContext jc = JAXBContext.newInstance("hoge.xsd");

        Unmarshaller u = jc.createUnmarshaller();

        Man man = (Man) u.unmarshal(new FileInputStream("hoge.xml"));

        System.out.println(man.getName());
        System.out.println(man.getAge());

        man.setName("baba");
        man.setName("21");

        Marshaller m = jc.createMarshaller();
        m.marshal(man, System.out);

        System.out.println("END");
    }
}

コンパイル、実行は、ここではIDEで行いました(Antでやっても同じです)。

実行結果

miya
10
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<man><name>21</name><age>10</age></man>

END

マーシャリングとアンマーシャリング(DTD編)

XMLスキーマは良く知らないので、普段使うDTDでも試してみました(そろそろXMLスキーマも勉強しないとなぁ)。ほとんど同じですが、xjcタスクでは、arg要素に-dtdを指定します。xjcタスクでは、XMLスキーマがデフォルトで、その他はオプション、実験的ツール扱いのようです。また、DTDを使う場合は、内部でdom4jが利用されているようなので、dom4jのJARもダウンロードし、クラスパスに通す必要があります。

hoge.dtd

<!ELEMENT man (name, age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>

build.xml抜粋

    <target name="dtd2java">
        <xjc schema="hoge.dtd" target="gensrc" package="hoge.dtd">
            <arg value="-dtd" />
        </xjc>
    </target>

Javaソースの方は、属性でなく、要素にセット、ゲットするときは、ちょっとめんどくさいことになっています。

DTDMain.java

import hoge.dtd.*;

import java.io.FileInputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class DTDMain {

    public static void main(String[] args) throws Exception {

        JAXBContext jc = JAXBContext.newInstance("hoge.dtd");

        Unmarshaller u = jc.createUnmarshaller();

        Man man = (Man) u.unmarshal(new FileInputStream("hoge.xml"));

        System.out.println(man.getName().getContent());
        System.out.println(man.getAge().getContent());

        ObjectFactory factory = new ObjectFactory();
        Name name = factory.createName();
        name.setContent("baba");
        man.setName(name);
        Age age = factory.createAge();
        age.setContent("21");
        man.setAge(age);

        Marshaller m = jc.createMarshaller();
        m.marshal(man, System.out);

        System.out.println("END");
    }
}

実行結果はXMLスキーマのときと同じものが出ます。

感想

うーん、Javaソースが出来ちゃって、XMLで読み書きできちゃうなんて素敵です。 JAXBを使う場面ですが、参考のページを読むと、スキーマに沿った形のXMLをオブジェクトにマッピングして操作したいときに使うらしいです(当たり前?)。単にXMLファイルの一部の値を読むだけとか、XSLTを使う場合とかには、JAXP(DOM、SAX)を利用する方がよいとのこと。しかし、簡単な例ならいいけど、ちょっと要素が増えると、ものすごいクラス数になりますね。。。

参考

@IT XML関連Javaテクノロジーの現在
そもそも、JAXシリーズって何じゃって話

Sun Microsystems - Technical Articles JAXB
JDCのJAXBの説明

The Java Web Services Tutorial
Webサービスのチュートリアル(英語)


TOP