連載 役に立つXMLツール集(2)
JAXBでデータバインディングに挑戦しよう

XMLプログラミングでは、DOMやSAXといったAPIを使用すると単調なコードを繰り返し書くことになり生産性が上がらないものだ。本連載では開発者が“楽をする”ために役立つXML関連ツールを紹介していく。(編集局)

www.netpotlet.com
原田洋子
2003/12/4

JAXBの概要

主な内容
JAXBの概要
JAXB参照実装の入手
セットアップ
開発手順
スキーマの作成
スキーマのコンパイル
アプリケーション作成
アプリケーション実行
文書操作アプリケーション
文書操作アプリケーションの実行
まとめ&サンプル・ダウンロード

 前回「XMLをJavaにマップするデータバインディング」では、データバインディングがどのようなものかといった概要を説明しました。今回からは実際にデータバインディングツールを使い、どのようにしてXMLモデルからオブジェクトモデルへのマッピングを行うのかを見ていきましょう。

 最初に取り上げるのはJAXB(The Java Architecture for XML Binding)です。JAXBはJavaの世界でいわゆる“標準”となるべく開発されているデータバインディングで、JavaのさまざまなAPI同様、仕様がJCP(Java Community Process)で決められ、参照実装(RI:Reference Implementation)がサン・マイクロシステムズからリリースされています。

 このようなスタイルで開発され、リリースされるAPIやツールを使うときに注意しておきたいのは、その名前が仕様を指しているのか実装を意味するのかという点です。通常、サン・マイクロシステムズがリリースする参照実装の名前は仕様名と同じです。ただし、仕様と実装ではバージョン番号が違いますし、サン・マイクロシステムズ以外のベンダや団体が仕様の実装をリリースしていることもあります。例えば、JAXB 1.0はJSR-31という番号で検討されたAPI仕様ですが、この参照実装であるデータバインディングツールの最新版(2003年11月時点)はJAXB 1.0.2です。また、ApacheがリリースしているXercesJAXP(Java API for XML Processing)を実装していますし、AxisSAAJ(SOAP with Attachments API for Java)を実装しています。混乱のもとなので気を付けましょう。

 本記事のプログラムは

を使用し、Linux上で動作を確認しています。

JAXB参照実装の入手

 JAXBの参照実装はJWSDP(Java Web Services Developer Pack)に含まれています。JWSDPはJAXB、JAXP、SAAJ、JSFなど、XMLやXMLベースの各種ツールをひとまとめにしたパッケージで、次のURLからダウンロードできます。

 http://java.sun.com/webservices/webservicespack.html

 2003年11月時点で、JWSDPの最新版は1.3です。JWSDPのバージョンが上がっても、含まれる参照実装のすべてのバージョンが上がるわけではありません。上記Webページや各ツールのリリースノートにバージョンが明記されているので確認してください。

 なお、JWSDPにはJAXBのバイナリのみが含まれていますが、JAXB Standard Implementation Projectからソースコードも入手できます。

セットアップ

 JAXBを使う前に必要なセットアップをやっておきましょう。これ以降の説明ではJWSDPをインストールしたディレクトリをJWSDP_HOMEと呼び、$JWSDP_HOMEで参照することにします。

アーカイブの構成

 JAXBの実行には次のアーカイブが必要です。

  • $JWSDP_HOME/jaxb/lib/*
  • $JWSDP_HOME/jwsdp-shared/lib/jax-qname.jar
  • $JWSDP_HOME/jwsdp-shared/lib/namespace.jar
  • $JWSDP_HOME/jwsdp-shared/lib/relaxngDatatype.jar
  • $JWSDP_HOME/jwsdp-shared/lib/xsdlib.jar
  • $JWSDP-HOME/jaxp/lib/endorsed/*

 この中で、最後のjaxp/lib/endorsedにあるアーカイブは、

  1. $JAVA_HOME/jre/lib以下にendorsedディレクトリごとコピーする
  2. java.endorsed.dirsシステムプロパティに$JWSDP_HOME/jaxp/lib/endorsedをセットする

のどちらかの方法でセットアップします。本記事では1つ目の方法で行いました。そのほかのアーカイブはクラスパスにセットします。

Eclipseのセットアップ

 本記事はEclipse上で開発/実行することを前提にしますので、クラスパスのセットアップはEclipse上で行います。ただし、Eclipseの詳細には触れませんので、@ITのEclipse関連記事「Eclipseを使おう!」などを参照してください。

1. Javaプロジェクト作成(例:valleyプロジェクト)
  ファイル → 新規 → プロジェクト → (画面
  Java(左ペイン) → Javaプロジェクト(右ペイン) → 次へ → (画面
  プロジェクト名(valley) → 終了 (画面

2. Javaのビルド・パス設定
  パッケージ・エクスプローラでプロジェクト(valley)選択 → 右クリック →
  プロパティー → (画面
  Javaのビルド・パス(左ペイン) → ライブラリー選択 →
  外部JARの追加 → 次のアーカイブを追加する (画面
  jaxb-api.jar, jaxb-impl.jar, jaxb-libs, jax-qname.jar, namespace.jar
  relaxngDatatype.jar, xsdlib.jar

3. フォルダ作成
  ソースフォルダ
  パッケージ・エクスプローラでプロジェクト(valley)選択 → 右クリック →
  新規 → ソース・フォルダ → (画面
  フォルダ名(src) → 終了 (画面

  スキーマ用フォルダ
  パッケージ・エクスプローラでプロジェクト(valley)選択 → 右クリック →
  新規 → フォルダ → (画面
  フォルダ名(schemas) → 終了 (画面

  XML文書用フォルダ
  パッケージ・エクスプローラでプロジェクト(valley)選択 → 右クリック →
  新規 → フォルダ → (画面
  フォルダ名(docs) → 終了 (画面

開発手順

 データバインディングを利用する場合、図1に示す手順で開発を進めます。最初に、XML文書の構造を定義したスキーマを作成します。次に、スキーマをコンパイルしますが、ここでXMLモデルからオブジェクトモデルへのマッピングが行われ、JavaのAPIが生成されます。マッピングというのはデータバインディングツールの主目的ですので、コンパイラは必ず用意されています。

 Java APIが生成されたらアプリケーションを作成します。アプリケーションはスキーマから生成されたAPIのみでプログラミングできるツールと、ほかのAPIも必要なツールがあります。JAXBは後者です。アプリケーションの実行にはXML文書を入力にするケースが多いと思われますが、XML文書は必須ではありません。ダイナミックに生成し、XML文書として出力するアプリケーションも作れます。また、URLやストリームからXML文書を読み込んだり、DOM(Document Object Model)のインスタンスを取り込むことも可能です。

 1 データバインディングツールを利用した開発手順

スキーマの作成

 とにかく最初に文書構造の定義を書かなくてはいけません。JAXBはXML Schemaがデフォルトのスキーマ言語ですが、試験実装という位置付けでRELAX NGDTDWSDLもサポートしています。XML Schemaについては

で連載記事が公開されているほか、次の書籍が出版されていますので、参考にしてください。

  • XML Schema』エリック・バン・デル ブリスト著 田村健人 ほか翻訳
    オライリージャパン ISBN487311120X

 JAXB 1.0が対応しているのはXML Schemaのサブセットです。非対応項目などの詳細については仕様書で確認してください。

 さて、前回取り上げたキーボードの例でスキーマを考えてみましょう。データバインディングツールは要素名や属性名をクラス名、メソッド名、変数名にそのまま使いますので、ここで日本語を使ってしまうととてもプログラミングしにくくなりますので変更しました。また、構造についてももうちょっとブラッシュアップして、PCと携帯電話のキーボードを表現できるようにします。さらに、キーサイズとキータイプは属性でも要素でも指定できるようにしてみます。例えば、リスト1やリスト2のように書けるようにすることを考えます。

 1  <?xml version="1.0" encoding="UTF-8"?>
 2  <keyboard>
 3    <key>
 4      <label type="number" default="true">1</label>
 5      <label type="charactor">!</label>
 6    </key>
 7    <key>
 8       <label type="charactor">a</label>
 9    </key>
10    <key attrSize="medium">
11      <label type="control">shift</label></key>
12    <key>
13      <label default="true"><type>number</type>2</label>
14      <label><type>charactor</type>@</label>
15    </key>
16    <key>
17      <size>large</size>
18      <label><type>control</type>space</label>
19    </key>
20  </keyboard>
リスト1 keyboard1.xml

 1  <?xml version="1.0" encoding="EUC-JP"?>
 2  <keyboard>
 3    <key>
 4      <label type="number" default="true">1</label>
 5      <label type="charactor">あ</label>
 6      <label type="charactor">い</label>
 7    </key>
 8    <key>
 9      <label type="number" default="true">2</label>
10      <label type="charactor">か</label>
11      <label type="charactor">A</label>
12    </key>
13    <key>
14      <label type="charactor" default="true">#</label>
15      <label type="control">記号</label>
16    </key>
17  </keyboard>
リスト2 keyboard2.xml

 すると、XML Schemaによる定義はリスト3のようになりますので、Eclipse上で次のようにしてkeyboard.xsdファイルを作成します。

4. スキーマファイルの作成
  パッケージ・エクスプローラでフォルダ schemas選択 → 右クリック →
  新規 → ファイル → (画面
  ファイル名 keyboard.xsd → 終了 (画面

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
 3   <xs:element name="keyboard">
 4     <xs:complexType>
 5       <xs:sequence>
 6         <xs:element minOccurs="0" maxOccurs="unbounded" ref="key"/>
 7       </xs:sequence>
 8     </xs:complexType>
 9   </xs:element>
10   <xs:element name="key">
11     <xs:complexType>
12       <xs:sequence>
13         <xs:group minOccurs="0" ref="size"/>
14         <xs:element maxOccurs="unbounded" ref="label"/>
15       </xs:sequence>
16       <xs:attributeGroup ref="size"/>
17     </xs:complexType>
18   </xs:element>
19   <xs:group name="size">
20     <xs:sequence>
21       <xs:element minOccurs="0" ref="size"/>
22     </xs:sequence>
23   </xs:group>
24   <xs:element name="size" type="size.list"/>
25   <xs:attributeGroup name="size">
26     <xs:attribute name="attrSize" type="size.list"/>
27   </xs:attributeGroup>
28   <xs:simpleType name="size.list">
29     <xs:restriction base="xs:token">
30       <xs:enumeration value="large"/>
31       <xs:enumeration value="medium"/>
32       <xs:enumeration value="small"/>
33     </xs:restriction>
34   </xs:simpleType>
35   <xs:element name="label">
36     <xs:complexType mixed="true">
37       <xs:sequence>
38         <xs:element minOccurs="0" ref="type"/>
39       </xs:sequence>
40       <xs:attribute name="default" type="xs:boolean"/>
41       <xs:attribute name="type" type="type.list"/>
42     </xs:complexType>
43   </xs:element>
44   <xs:element name="type" type="type.list"/>
45   <xs:simpleType name="type.list">
46     <xs:restriction base="xs:token">
47       <xs:enumeration value="control"/>
48       <xs:enumeration value="charactor"/>
49       <xs:enumeration value="number"/>
50     </xs:restriction>
51   </xs:simpleType>
52 </xs:schema>
リスト3 keyboard.xsd (2004年6月15日訂正☆お詫び

☆お詫び

XML & Web Services 会議室」でご指摘いただいたとおり、リスト3 keyboard.xsdには誤りがありましたので正しいものに修正しました。手違いにより動作確認前のスキーマを掲載していました。お詫び申し上げます。なお、サンプルコードのアーカイブvalley.zipには正しいkeyboard.xsdが含まれていましたので、修正の必要はありません。

スキーマのコンパイル

 JAXBのコンパイラはxjcと呼ばれています。xjcはコマンドラインで実行できるほか、AntのタスクXJCTaskも用意されています。AntはEclipse環境にも組み込まれていますので、ここではAntを使ってコンパイルします。

Antはmakeに代わるJavaで作られたビルドツールです。makeよりも機能が豊富で、プラットフォームに依存しないので、幅広く使われるようになったツールです。

 リスト4のビルドファイルを次のように作成します。

5. ビルドファイルの作成
  パッケージ・エクスプローラでプロジェクト(valley)選択 → 右クリック →
  新規 → ファイル → (画面
  ファイル名 build.xml → 終了 (画面
  ( → リスト4のようにビルドファイルを作成 → 保存)

 リスト4のbuild.xmlは図2のディレクトリ構成になっていることを想定しています。プロパティjwsdp.homeには環境に合わせて$JWSDP_HOMEの値に変更してください。また、XML Schema以外のスキーマ言語による定義を使う場合、XJCTask実行時のオプションで明示しなければなりません。XJCTaskの使用方法は$JWSDP_HOME/jaxb/docs/ant.htmlに説明がありますので参照してください。

2 valleyプロジェクトのディレクトリ構成


 1  <?xml version="1.0"?>
 2  <project default="compile" basedir=".">
 3    <property name="jwsdp.home"
                value="/usr/local/java/xml/jwsdp-1.3"/>
 4    <property name="schema.dir" value="schemas"/>
 5    <property name="src.dir" value="src"/>
 6    <property name="schema" value="keyboard.xsd"/>
 7    <property name="package" value="com.netpotlet.kayak"/>
 8    
 9    <path id="classpath">
10      <pathelement path="."/>
11      <fileset dir="${jwsdp.home}" includes="jaxb/lib/*.jar"/>
12      <fileset dir="${jwsdp.home}"
                 includes="jwsdp-shared/lib/*.jar"/>
13    </path>
14    
15    <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
16      <classpath refid="classpath"/>
17    </taskdef>
18    
19    <target name="compile">
20      <echo message="Compiling the schema..."/>
21      <xjc schema="${schema.dir}/${schema}"
             target="${src.dir}" package="${package}"/>
22    </target>
23  
24  </project>
リスト4 build.xml

 ビルドファイルを作成したら、設定して実行します。

6. ビルドの実行
  実行 → 外部ツール → 外部ツール → (画面
  Antビルド選択 → 新規 → (画面
  ロケーション/基本ディレクトリ設定(図3参照) → 適用 → 実行

3 Ant実行のための設定(クリックで拡大します)

 2回目以降のAnt実行は図4に示す外部ツール実行ボタンをクリックするだけです。

4 外部ツール実行ボタン

 ビルドが成功するとソースフォルダにリスト2のpackageプロパティ(7行目)で指定したパッケージとソースコードが自動生成されます。生成された時点ではEclipse上に表示されませんので、次のようにしてワークベンチを最新の状態にします。このとき自動生成されたソースコードがコンパイルされます。

7. ワークベンチの更新
  パッケージ・エクスプローラでプロジェクト(valley)選択 → 右クリック →
  最新表示 (画面1画面2

アプリケーション作成

 JAXBはスキーマから3つのパッケージと各パッケージに属するクラス/インターフェイスを自動生成します。本記事のサンプルの場合、

  • com.netpotlet.kayak:インターフェイス/ファクトリ
  • com.netpotlet.kayak.impl:インターフェイスの実装
  • com.netpotlet.kayak.impl.runtime:実行時に必要なAPI

が作られます。アプリケーションを作る場合、通常、com.netpotlet.kayakのインターフェイス/ファクトリとjavax.xml.bindパッケージのAPIを使います。

 手始めに読み込みと検証を行うアプリケーションを作ってみたのが、リスト5 JaxbReaderクラスです。XML文書の読み込みはアンマーシャル(Unmarshal)といい、javax.xml.bind.Unmarshallerインターフェイスを使います(23〜24行目)。検証(バリデーション:Validation)が必要な場合はUnmarhallerのメソッドで指定します(22行目)。各要素や属性を取得するときに、スキーマから自動生成されたAPIを使います(31〜74行目)。

 リスト5はパッケージcom.netpotlet.testに属するクラスとして定義しましたので、次のようにしてパッケージ/クラスを作ります。

8. パッケージ/クラスの作成
  パッケージ・エクスプローラでソース・フォルダ(src)選択 → 右クリック →
  新規 → パッケージ → (画面
  パッケージ名(com.netpotlet.test) → 終了 (画面

  パッケージ・エクスプローラでパッケージ(com.netpotlet.test)選択 →
  右クリック → 新規 → クラス → (画面
  クラス名(JaxbReader) → 終了 (画面

 1  package com.netpotlet.test;
 2  
 3  import java.io.File;
 4  import java.util.List;
 5  
 6  import javax.xml.bind.JAXBContext;
 7  import javax.xml.bind.JAXBException;
 8  import javax.xml.bind.Unmarshaller;
 9  
10  import com.netpotlet.kayak.Key;
11  import com.netpotlet.kayak.Keyboard;
12  import com.netpotlet.kayak.Label;
13  import com.netpotlet.kayak.Type;
14  
15  public class JaxbReader {
16      private Keyboard keyboard;
17      
18      JaxbReader(String packagename, String filename)
19          throws JAXBException {

            //おきまり。このようにしてコンテキストと
            //アンマーシャラーを取得する
20          JAXBContext context =
                JAXBContext.newInstance(packagename);
21          Unmarshaller unmarshaller =
                context.createUnmarshaller();

            //検証機能を有効にする
22          unmarshaller.setValidating(true);
            
            //XML文書を読み込む(アンマーシャル)
23          keyboard =
24              (Keyboard)unmarshaller.unmarshal(
                    new File(filename));
25      }
26      
27      Keyboard getKeyboard() {
28          return keyboard;
29      }
30      
31      private void report() {
32          String newline = System.getProperty("line.separator");
33          String defaultSize = "small";
34          String value;
35  
            //要素 key のリストを取り出す
36          List keys = keyboard.getKey();
37          StringBuffer sb = new StringBuffer();
38          for (int i=0; i<keys.size(); i++) {
39              Key key = (Key)keys.get(i);

                //属性か要素にセットされているsizeを取得する
40              sb.append("size: ");
41              if ((value = key.getAttrSize()) != null) {
42                  sb.append(value);
43              } else if ((value = key.getSize()) != null) {
44                  sb.append(value);
45              } else {
46                  sb.append(defaultSize);
47              }

                //要素labelのリストを取り出す
48              List labels = key.getLabel();
49              for (int j=0; j<labels.size(); j++) {
50                  sb.append(" [");
51                  Label label = (Label)labels.get(j);

                    //この要素がdefault指定かどうかをチェックする
52                  if (label.isDefault()) {
53                      sb.append("(default)");
54                  }

                    //属性にセットされているtypeを取得する
55                  sb.append("type: ");
56                  if ((value = label.getType()) != null) {
57                      sb.append(value);
58                  }

                    //要素にセットされているtypeか
                    //label要素のテキストを取得する
59                  List contents = label.getContent();
60                  for (int k=0; k<contents.size(); k++) {
61                      Object obj = contents.get(k);
62                      if (obj instanceof Type) {
63                          sb.append(((Type)obj).getValue());
64                      } else {
65                          sb.append(", label: ");
66                          sb.append(obj.toString());
67                          sb.append("]");
68                      }
69                  }
70              }
71              sb.append(newline);
72          }
73          System.out.println(new String(sb));
74      }
75  
76      public static void main(String[] args) throws Exception {
77          if (args.length < 2) {
78              throw new Exception("arguments are not enough");
79          }
80          JaxbReader reader =
81              new JaxbReader(args[0], args[1]);
82          reader.report();
83      }
84  }
リスト5 JaxbReader.java

アプリケーション実行

 XML文書の読み込みと検証を行うアプリケーションを実行してみましょう。このアプリケーションはJAXBが自動生成するAPIのパッケージ名とXML文書を実行時の引き数から取得するので、次のように設定、実行します(図5、6参照)。なお、XML文書は図2のdocsディレクトリに置いてあります。

9. アプリケーションの実行(JaxbReader
  実行 → 実行... → (画面
  Javaアプリケーション → 新規 → メインタブ →
  プロジェクト名(valley)/メイン・クラス(com.netpotlet.test.JaxbReader)
  → (画面
  引き数タブ → プログラム引き数(com.netpotlet.kayak docs/keyboard1.xml) → (画面
  適用 → 実行

5 実行アプリケーションの設定(クリックで拡大します)


6 実行時の引き数指定

 XML文書が正しく書けていれば次のように出力されます。

size: small [(default)type: number, label: 1] [type: charactor, label: !]
size: small [type: charactor, label: a]
size: medium [type: control, label: shift]
size: small [(default)type: number, label: 2] [type: charactor, label: @]
size: large [type: control, label: space]
コンソール1 JaxbReaderの出力

 ここで、例えばリスト1の5行目の開始/終了タグをlebelと書き換えて実行すると、次のように出力され検証をパスしなかったことが分かります。

DefaultValidationEventHandler: [ERROR]: 要素"lebel"はここには書けません。書けるのは: <label>
Location: line 6 of file:/home/yoko/niue/workspace/valley/docs/keyboard1.xml
Exception in thread "main" com.sun.msv.verifier.ValidityViolation: 要素"lebel"はここには書けません。書けるのは: <label>
at com.sun.msv.verifier.Verifier.onError(Verifier.java:332)
.........
.........
コンソール2 JaxbReaderのエラー出力

文書操作アプリケーション

 要素や属性を追加してXML文書を出力するアプリケーションも試してみましょう。リスト6 JaxbCreatorクラスがそのような機能のあるサンプルです。XML文書の出力はマーシャル(Marshal)といい、javax.xml.bind.Marshallerインターフェイスを使います(21〜24行目)。新たに要素を作り出す場合には、JAXBがスキーマから自動生成したObjectFactoryクラスのcreate<要素名>()というメソッドを使います(50、61行目)。

 1  package com.netpotlet.test;
 2  
 3  import javax.xml.bind.JAXBContext;
 4  import javax.xml.bind.JAXBException;
 5  import javax.xml.bind.Marshaller;
 6  
 7  import com.netpotlet.kayak.Key;
 8  import com.netpotlet.kayak.Keyboard;
 9  import com.netpotlet.kayak.Label;
10  import com.netpotlet.kayak.ObjectFactory;
11  
12  public class JaxbCreator {
13      private Keyboard keyboard;
14      
15      JaxbCreator(String packagename, String filename)
                throws JAXBException {
            //要素や属性を作るときはObjectFactoryを使う
16          ObjectFactory objFactory = new ObjectFactory();

            //元文書を取得する
17          keyboard =
18              (new JaxbReader(
                    packagename, filename)).getKeyboard();

            //文書にいくつかの要素を追加する
19          updateDocument(objFactory);

            //おきまり。このようにしてコンテキストと
            //マーシャラーを取得する
20          JAXBContext context =
                JAXBContext.newInstance(packagename);
21          Marshaller marshaller =
                context.createMarshaller();

            //出力を整形する
22          marshaller.setProperty(
                Marshaller.JAXB_FORMATTED_OUTPUT,
                Boolean.TRUE);

            //日本語を含む場合にこの指定が必要
23          marshaller.setProperty("jaxb.encoding", "euc-jp");

                //標準出力に表示する
24          marshaller.marshal(keyboard, System.out);
25      }
26      
27      private void updateDocument(ObjectFactory objFactory)
                throws JAXBException {
28          String[] labels1 = {
29              "う", "え", "お"
30          };
31          String[] labels2 = {
32              "な", "に", "ぬ", "ね", "の"
33          };

            //1つ目のkey要素にlabel要素を追加する
34          Key key1 = (Key)keyboard.getKey().get(0);
35          updateKey(objFactory, key1, labels1);

            //3つ目にlabel要素を含むkey要素を追加する
36          Key key2 = createKey(objFactory, labels2);
37          keyboard.getKey().add(2, key2);
38      }
39      
40      private void updateKey(ObjectFactory objFactory,
41                             Key key,
42                             String[] labels)
                throws JAXBException {
43          for (int i=0; i<labels.length; i++) {
44              key.getLabel().add(getLabel(objFactory,
                                            "charactor",
                                            labels[i]));
45          }
46      }
47      
48      private Key createKey(ObjectFactory objFactory,
49                            String[] labels)
               throws JAXBException {
50          Key key = objFactory.createKey();
51          key.getLabel().add(getLabel(objFactory,
                                        "number", "5"));
52          for (int i=0; i<labels.length; i++) {
53              key.getLabel().add(getLabel(objFactory,
                                   "charactor", labels[i]));
54          }
55          return key;
56      }
57      
58      private Label getLabel(ObjectFactory objFactory,
59                             String type,
60                             String text) throws JAXBException {
61          Label label = objFactory.createLabel();
62          label.setType(type);
63          label.getContent().add(text);
64          return label;
65      }
66      
67      public static void main(String[] args) throws Exception {
68          if (args.length < 2) {
69              throw new Exception("arguments are not enough");
70          }
71          new JaxbCreator(args[0], args[1]);
72      }
73  }
リスト6 JaxbCreator.java

文書操作アプリケーションの実行

 このアプリケーションも実行してみましょう。今度もJAXBが自動生成するAPIのパッケージ名とXML文書を実行時の引き数から取得するので、次のように設定、実行します。今度も、XML文書は図2のdocsディレクトリに置いてあります。

10. アプリケーションの実行(JaxbCreator
  実行 → 実行... →
  Javaアプリケーション → 新規 → メインタブ →
  プロジェクト名(valley)/メイン・クラス(com.netpotlet.test.JaxbCreator)
  → (画面
  引き数タブ → プログラム引き数(com.netpotlet.kayak docs/keyboard2.xml) → (画面
  適用 → 実行

 問題なく実行されれば、次のように出力されます。

<?xml version="1.0" encoding="euc-jp" standalone="yes"?>
<keyboard>
    <key>
        <label default="true" type="number">1</label>
        <label type="charactor">あ</label>
        <label type="charactor">い</label>
        <label type="charactor">う</label>
        <label type="charactor">え</label>
        <label type="charactor">お</label>
    </key>
    <key>
        <label default="true" type="number">2</label>
        <label type="charactor">か</label>
        <label type="charactor">A</label>
    </key>
    <key>
        <label type="number">5</label>
        <label type="charactor">な</label>
        <label type="charactor">に</label>
        <label type="charactor">ぬ</label>
        <label type="charactor">ね</label>
        <label type="charactor">の</label>
    </key>
    <key>
        <label default="true" type="charactor">#</label>
        <label type="control">記号</label>
    </key>
</keyboard>
コンソール3 JaxbCreatorの出力

 なお、実行設定後に繰り返し実行する場合は図7に示すように実行ボタンをクリックするだけです。

7 実行ボタン

まとめ&サンプル・ダウンロード

 JAXBを使った簡単なアプリケーションを試してみましたが、いかがだったでしょうか。DOMやSAXでのプログラミング経験がある読者なら、かなりシンプルで理解しやすいコードになっていることが分かるでしょう。

 特に、新規に要素を追加する場合、データバインディングツールを利用していると、定義にない構造は作れないようになっているので、検証にパスしない文書を作ってしまうことはありません。XSLTへの変換などの後処理がある場合は特に便利でしょう。

 JAXBにはここで取り上げた以外にもさまざまな機能がありますので、ひととおりデータバインディングツールの説明をした後で、再度、取り上げる予定です。

 今回のサンプルの動作確認はEclipseで行いましたが、最終的にvalleyプロジェクトは図8に示す構成になりました。

8 valleyプロジェクトのディレクトリ構成(2)

 今回使用したプログラムやファイル類は以下からダウンロードできます。

  • valley.zip(212Kbytes)
     
    Windows環境で利用される場合、euc-jpをWindows-31Jなど適当なエンコーディングに変更してください。また、日本語を含むファイルはEUC-JPになっていますので、あらかじめ文字コードを変えてから利用されるといいでしょう。

 次回はCastorを取り上げる予定です。お楽しみに。(次回に続く

======== my confessions ========

「XML Schemaによる定義はこのようになります」とさらりといってのけましたが、実は、筆者はRELAX NGは書けるものの、XML Schemaは書けません (^^; 。そこで、XML Schemaがいるときはどうするかというと、取りあえずRELAX NGで定義を書いてtrangというツールで変換します。trangというのはXSLTをはじめ、数々の仕様やツールの作者としてXML分野で有名なJames Clark氏が作られた変換ツールです。Trangはhttp://thaiopensource.com/relaxng/trang.htmlからダウンロードできます。今回の記事で使用したソースコード一式にRELAX NGによる定義も入れておきましたので、XML Schemaによる定義と見比べてください。なぜ、RELAX NGなら書けるのか分かるのではと思います。


関連記事

 ・SEのためのXML Schema入門
 ・XMLテクニック集
 ・Javaで実現するDOM/SAXプログラミング



「連載 役に立つXMLツール集」


XML & SOA フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日月間