連載 XMLツールでプログラミング(4)
Javaで文書作成クラスを作成する

DTDに従った妥当なXML文書をJavaで生成する場合、DOM APIを利用して妥当性をチェックしながらプログラムを組むのは手間がかかる。XML Class Generator for Javaを利用すると、あらかじめ定義されたDTDからJavaクラスを生成し、そのDTDに従ったXML文書を生成するプログラムが容易に作成できるようになる。

赤木伸
日本オラクル株式会社
2000/11/7

 XML文書の構造を定義するスキーマ言語の1つに、DTDがある。このDTDをあらかじめ決めておくことで、統一的なXML文書を作成することができる。例えば、BtoBなどでデータのやりとりにXML文書を利用する際には、送り手と受け手が共通のDTDを決めておけばデータ構造にあいまいさのないXML文書を作れる。そのため、送り手と受け手のアプリケーションは、決まった形式のXML文書に対応すればよく、処理が容易になり間違いも少なくなる。

 このように、すでにDTDが決まっており、このDTDに従った妥当なXML文書をアプリケーションで作成したい場合、どうしたらいいだろうか。DOM APIを使用して、DTDに従うように1つずつ要素などを追加していくのだろうか。その場合のプログラムの動作としては、ElementやNodeなどのオブジェクトを生成し、DTDを開発者が確認して要素名などを指定していくだろう。利用しているXMLパーサがOracle XML Parserであれば、validateElement()といったメソッドで、XML文書の妥当性のチェックを随時行っていくような感じになるかと思う。

 DOMツリーに対して複雑な処理を行う場合にはDOM APIを利用した方がいいが、この例のように単にDTDに従ったXML文書を生成する場合には、DOM APIを操作する方法はあまり便利とは言えない。

 そこで登場するのが、Oracle XML Class Generator for Java(v.1.0.2)(以下Class Generator)である。Class Generatorは、DTDに基づいてJavaのクラスを生成する。そして各要素ごとにそれぞれクラスを作り、そのクラスを用いることで、DTDに従った妥当なXML文書を生成することができる。これを利用すれば、いちいちDOM APIを操作する必要がなくなるため、すでにDTDがある場合などに、アプリケーション間でXML文書をやりとりするときなどに便利になる。今回はこのClass Generatorを紹介していこう。

   DTDを持つXML文書

 以下ではClass Generatorを使用して、DTDに従った妥当なXML文書を生成するアプリケーションの作成手順を解説する。

 まず、以下のようなXML文書「Emp.xml」を生成するプログラムを作成したいとする。

生成したいXML(Emp.xml)

<?xml version = '1.0' encoding = 'Shift_JIS'?>
<!DOCTYPE ROWSET SYSTEM "file:/F:/jvm/emp.dtd">
<ROWSET>
<ROW num="1">
<EMPNO>1111</EMPNO>
<ENAME>平田陽彦</ENAME>
</ROW>
<ROW num="2">
<EMPNO>2222</EMPNO>
<ENAME>木村誠介</ENAME>
</ROW>
<ROW num="3">
<EMPNO>3333</EMPNO>
<ENAME>岡内大昌</ENAME>
</ROW>
</ROWSET>

 このXML文書の構造(スキーマ)を表すDTDは次のようになる。ファイル「Emp.dtd」として参照できる。

XML文書のDTD(Emp.dtd)

<!ELEMENT ROWSET (ROW)*>
<!ELEMENT ROW (EMPNO,(ENAME)?)>
<!ATTLIST ROW num CDATA #REQUIRED >
<!ELEMENT EMPNO (#PCDATA)*>
<!ELEMENT ENAME (#PCDATA)*>

 簡単にこのDTDを解説すると、「ROWSET」という要素には、0個以上(「*」は0以上)の「ROW」要素が含まれる。この「ROW」要素は、1個の「EMPNO」要素と0個または1個(「?」は0または1)の「ENAME」要素で構成される。また、この「ROW」要素には、「num」という属性がある。そして、「EMPNO」と「ENAME」の2つの要素はテキストデータが含まれる。上の「Emp.xml」を見てみると確かに、DTDに従っていることが分かる。

   DTDからJavaのクラスを生成する

 Class Generatorのsampleというディレクトリに、SampleMain.javaというクラスが入っている。このクラスはClass Generatorのクラスを使用したサンプルになっており、DTDをこのクラスの実行時に引数として渡すと、各要素ごとに1つずつクラスが生成される。以下のソースコードは、このSampleMain.javaを少し変更したものになっている。

 このクラスをコンパイルし、実行する。

% java SampleMain -root ROWSET Emp.dtd

 実行すると、各要素ごとにクラスが生成される。このDTDには、「ROWSET」、「ROW」、「EMPNO」、「ENAME」の4つの要素が定義されているので、各要素ごとに、

  • ROWSET.java
  • ROW.java
  • EMPNO.java
  • ENAME.java

上記の4つのソースファイルが自動的に生成される。

   JavaクラスからXML文書を生成する

 次に、この4つのクラスをコンパイルし、その後、これらのクラスを使用してXML文書を生成するプログラムを書いていく。

 この生成された4つのクラスで何ができるかを説明しよう。まずROWSETクラス(ROWSET.java)では、

  1. ROWオブジェクトを子ノードとして追加するメソッド
  2. XML文書を出力するメソッド

上記の2つが定義されている。以下はそのリストの抜粋。

ROWSET.java
public class ROWSET extends CGDocument {
  public static DTD globalDTD;
  …
  public ROWSET()
  public void addNode(ROW R) ……(1)
  …
  public void print(OutputStream out) ……(2)
  public void print(OutputStream out, String enc)
}

次にROWクラス(ROW.java)では、

  1. EMPNOオブジェクト、またはENAMEオブジェクトを子ノードとして追加するメソッド
  2. 「num」属性を設定するメソッド

 上記の2つが定義される。以下はそのリストの抜粋。

ROW.java
public class ROW extends CGNode {
  …
  public ROW(String varNum)
  public void addNode(EMPNO E) ……(1)
  public void addNode(ENAME E)
  …
  public void setNum(String theData) ……(2)
}

 最後に、EMPNOクラスとENAMEクラスであるが、この2つは、持っているメソッドなどは変わらない。

EMPNO.java (ENAME.java)
  public class EMPNO extends CGNode {
    …
  public EMPNO() ……(1)
  public EMPNO(String theData)
  public void addData(String theData) ……(2)
  public void addCDATASection(String theData) ……(3)
  …
}

この2つのクラスでは、コンストラクタは2種類ある。1つは、ただインスタンス化するもので、もう1つはインスタンス化の際に、テキストデータも設定してしまうものである。

  1. テキストデータを設定するメソッド
  2. CDATAセクションを生成するメソッド

 2についてさらに説明しよう。CDATAセクションは、タグ付けに使用する文字(「<」や「&」など)を認識しないようにするときに使用する。たとえば、<ENAME>要素の内容が「<&abc」の場合、

ename.addData("<&abc")

とすると、

<ENAME>&lt;&amp;abc</ENAME>

と変換されて出力される。
(注:2001年2月現在提供されているXDKでは、XDKの障害によりこの機能が正常に働きません。今後のバージョンで修正される予定だそうです)

 これを、addCDATASection()メソッドを使って、

ename.addCDATASection("<&abc");

とすると

<ENAME><![CDATA[<&abc]]></ENAME>

と出力され、「<」や「&」は変換されない。

   JavaがXML文書を自動生成してくれる

 では、さっそくこれらのクラスを使ってXML文書を生成するプログラムを書いてみる。

CreateXML.java(クリックでファイルを参照可能)

このプログラムは以下の内容を持つ。

  1. ROWSETクラスをインスタンス化している
  2. ROWクラスを3つインスタンス化している。コンストラクタには、「num」属性の値を渡している
  3. EMPNOクラスをインスタンス化している。enum1のように、コンストラクタに要素の内容を渡す方法と、enum2のように後で、addData()メソッドを使用して要素の内容を指定する方法がある
  4. addNode()メソッドで、EMPNOオブジェクトとENAMEオブジェクトをROWオブジェクトに追加している
  5. 同様に、ROWSETオブジェクトにROWオブジェクトを追加している
  6. ファイルに書き出している。

このソースをコンパイルし、実行すると、以下のようなXML文書が生成される。

Emp.xml

<?xml version = '1.0' encoding = 'Shift_JIS'?>
<!DOCTYPE ROWSET SYSTEM "file:/F:/jvm/Emp.dtd">
<ROWSET>
  <ROW num="1">
    <EMPNO>1111</EMPNO>
    <ENAME>平田陽彦</ENAME>
  </ROW>
  <ROW num="2">
    <EMPNO>2222</EMPNO>
    <ENAME>木村誠介</ENAME>
  </ROW>
  <ROW num="3">
    <EMPNO>3333</EMPNO>
    <ENAME>岡内大昌</ENAME>
  </ROW>
</ROWSET>

   DOMを操作するよりもずっと簡単に

 このように、すでにDTDがあり、それに従った妥当なXML文書を作成したい場合には、XML Class Generatorを利用すると便利である。XML Class Generatorでは、ある要素は、その要素専用のクラスのインスタンスとして表され、要素の追加などは専用のメソッドが用意されるため、XML文書を直感的に作成することができる。

 また、この例のように、要素の操作といった複雑な処理をせずに、ただ単に、すでにあるDTDに従った妥当なXMLを出力したい場合には、XML Class Generatorを利用した方がDOM APIを利用するより圧倒的に簡単である。

Index
連載 XMLツールでプログラミング
  (1)Javaで利用するXML開発ツール
Oracle XML Developer's Kit(XDK)の紹介
  (2)DOMによるXML文書の操作
DOM APIを使ったプログラムの基礎
  (3) SAXによるXML文書の操作
SAX APIを使ったXML文書操作の基礎と実践
(4) Javaで文書作成クラスを生成する
DTDを元に、XML文書を作成するJavaクラスを作る
  (5) OracleからXML文書を出力する
データベースへの問い合わせ結果をXML文書にする

 



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

注目のテーマ

HTML5+UX 記事ランキング

本日月間