RelaxNGCCは、RELAX NGスキーマを読んでJavaのソースコードを生成するツールです。生成されたソースコードは、そのスキーマに合ったXML文書を読んだときにユーザがスキーマに埋め込んでおいた動作をします。
次のようなXML文書を考えます。これは2001年8月15日のサッカーの試合(日本対オーストラリア)での、日本代表のスターティングメンバーです。
<?xml version="1.0" encoding="shift_jis"?> <team> <player number="1" ><name>川口能活</name></player> <player number="3" ><name>松田直樹</name></player> <player number="4" ><name>森岡隆三</name></player> <player number="16"><name>中田浩二</name></player> <player number="21"><name>波戸康広</name></player> <player number="14"><name>伊東輝悦</name></player> <player number="17"><name>戸田和幸</name></player> <player number="6" ><name>服部年弘</name></player> <player number="8" ><name>森島寛晃</name></player> <player number="9" ><name>柳沢敦</name></player> <player number="22"><name>鈴木隆行</name></player> </team>
ここには team エレメントの中に player エレメントがあり、player エレメントは number アトリビュートと name エレメントを持っています。この構造を記述するRELAX NG文法は次のようになります。
<?xml version="1.0" encoding="utf-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes" xmlns:c="http://www.xml.gr.jp/xmlns/relaxngcc"> <start c:class="sample1"> <element name="team"> <oneOrMore> <element name="player"> <attribute name="number"> <data type="positiveInteger" c:alias="number"/> [1] <c:java>System.out.println(number);</c:java> [2] </attribute> <element name="name"> <text c:alias="name"/> [3] <c:java>System.out.println(name);</c:java> [4] </element> </element> </oneOrMore> </element> </start> </grammar>
RelaxNGCC固有の追加情報(namespace prefix "c" がついています)は赤いところです。まず、numberアトリビュートの中身をしめすdataエレメント[1]に注目してください。ここにaliasアトリビュートがついています。aliasアトリビュートは、XML文書中のデータをJavaからアクセスできるようにするためのものです。こうすることでnumberという変数でこのdataエレメント(XMLインスタンスではnumberアトリビュートの値)の値にアクセスできます。同様に、nameエレメントの中身[3]にもnameという名前でアクセスできるようにしています。
次に、"java"エレメント([2],[4])です。これは、XML文書を読んだときに実行するJavaコード断片を記述したものです。ここでは文書の中身を確認するためにSystem.outに出力しています。
さらに、これら全体はoneOrMore内に入っているので、コードはplayerエレメントの個数だけ繰り返し実行されることになります。
では、これをRelaxNGCCにかけてみます。
$ java -classpath msv.jar;relaxngcc.jar relaxngcc.RelaxNGCC sample1.rxm
そうすると、カレントディレクトリにJavaのソースファイルが出力されます。これの一部は次のようになっています。完全なものはここにあります。
import java.math.BigInteger; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import relaxngcc.runtime.NGCCPlainHandler; import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.ParserConfigurationException; class sample1 extends NGCCPlainHandler { public static final String DEFAULT_NSURI = ""; private int _ngcc_current_state; private String name; private String number; (中略) public void enterElement(String uri,String localname,String qname) throws SAXException { if(_ngcc_current_state==1) { if(localname.equals("player") && uri.equals(DEFAULT_NSURI)) { _ngcc_current_state=7; processAttribute(); } (中略) public void text(String value) throws SAXException { if(_ngcc_current_state==4) { { name=value;System.out.println(name); _ngcc_current_state=3; } } else if(_ngcc_current_state==6) { { number=value;System.out.println(number); _ngcc_current_state=5; } } } }これをコンパイルして実行すると、
$ javac -classpath msv.jar:relaxngcc.jar:. sample1.java $ java -classpath msv.jar:relaxngcc.jar:. sample1.java sample1.xml 1 川口能活 3 松田直樹 4 森岡隆三 16 中田浩二 21 波戸康広 14 伊東輝悦 17 戸田和幸 6 服部年弘 8 森島寛晃 9 柳沢敦 22 鈴木隆行
となります。
このように最も基本的なRelaxNGCCの使い方は、dataまたはtextエレメントにaliasアトリビュートを使って名前を付け、javaエレメントでコードを埋め込むことです。javaエレメント内からはJavaでできるあらゆることが可能なので、外部のライブラリを呼んだりデータベースにアクセスしたりといったことも簡単です。