# RelaxNGCC チュートリアル１

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でできるあらゆることが可能なので、外部のライブラリを呼んだりデータベースにアクセスしたりといったことも簡単です。

RelaxNGCC home