四則演算のXML Schema

Scala に wonderfl のゲームを移植しようとして諦めてしまった今日この頃、いかがお過ごしでしょうか?

自分は仕事でXML Schemaをやりそうで、やってません。
でも、XML Schemaを久しくいじってなかったので勉強しようとして、
俺言語プログラマ的には、四則演算のXMLのバリデーションができるサンプルがほしいと
思ってググってみるも、見つからない。むぅ。
Visual StudioMSDN だけだと、わかりずらい。むぅ。
いいエディタなんかないか?ってさがすと、NetBeansXMLスキーマが案外よさそう。
ってことで、使ってみたら、MSDN+ Visual Studioより自分の場合はわかりやすくできました。
おお、すばらしい。
ということで、まず、バリデーションしたいXMLが以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<exp xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
   xmlns='http://xml.netbeans.org/schema/exp'
   xsi:schemaLocation='http://xml.netbeans.org/schema/exp exp.xsd'>
       <add>
           <div>
               <sub>
                   <number>2</number>
                   <number>2</number>
               </sub>
               <number>3</number>
           </div>
           <add>
               <number>2</number>
               <number>2</number>
           </add>
       </add>
</exp>

expがルートのタグでその下に、add,mul,sub,divという演算子用タグとnumberという数値用タグが入れられます。
で、演算子タグは2つの子要素をもてますというやつです。再帰的に文法を定義できるといいなというところ。
で、これに対応する XML Schema がこちら。

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://xml.netbeans.org/schema/exp"
    xmlns:tns="http://xml.netbeans.org/schema/exp"
    elementFormDefault="qualified">

    <xsd:element name="exp">
        <xsd:complexType>
            <xsd:group ref="tns:exp"/>
        </xsd:complexType>
    </xsd:element>

    <xsd:group name="exp">
        <xsd:choice>
            <xsd:element name="number">
                <xsd:simpleType>
                    <xsd:restriction base="xsd:short"/>
                </xsd:simpleType>
            </xsd:element>

            <xsd:element name="add">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:group ref="tns:exp"/>
                        <xsd:group ref="tns:exp"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>

            <xsd:element name="sub">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:group ref="tns:exp"/>
                        <xsd:group ref="tns:exp"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>

            <xsd:element name="mul">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:group ref="tns:exp"/>
                        <xsd:group ref="tns:exp"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>

            <xsd:element name="div">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:group ref="tns:exp"/>
                        <xsd:group ref="tns:exp"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
        </xsd:choice>
    </xsd:group>

</xsd:schema>

簡単に説明すると、まず、schemaタグがルートのタグでその下あるelementタグがルート要素になりうるタグになります。今回はexpタグをルートにしたいので、こんな感じに書きます。xsd:っていうのは名前空間ってやつで、schamaタグで xmlns:xsd="http://www.w3.org/2001/XMLSchema"こんな風に定義されているものです。
XML Schemaのタグは全部xsd:をつけて書くぜってかんじですな。
で、elementタグ以下のcomplexTypeとかいうのが、最初なんだ?complex?虚数?とか思うのですが複合型といわれる型です。Cとかだとstructやらclassみたいなものと考えるとわかりやすいかと。大してプリミティブな型みたいなのがsimpleTypeだと。simple型は、intとかstringとか組み合わせもなんもない型が主だと思ってしまいましょう。
すると、今回のexpの下にはいろんなタグが入るからcomplexTypeを選択するしかないわけです。ってことでそれがcomplexTypeです。
で、その下にとグループを書いてます。refっていうのは参照っていう意味でCとかにたとえれば、関数呼び出しみたいなものです。グループにはいろんな要素を1つにまとめる機能があります。
なんで、groupを使っているのかというと、elementだけで定義すると限界があったからです。
どんな限界かというと、下の例を見てもらいたいと。

<?xml version="1.0" encoding="UTF-8"?>
<!-- xml schema の定義は、schemaタグ内に書く-->
<xsd:schema
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://xml.netbeans.org/schema/exp1"
    xmlns:tns="http://xml.netbeans.org/schema/exp1"
    >
    <!--
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"は
        xsdネームスペースに http://www.w3.org/2001/XMLSchema を使う。xsd:...タグはXMLSchemaのタグだ!ってこと
        targetNamespace="http://xml.netbeans.org/schema/exp1"は
        今回作るスキーマのネームスペースは"http://xml.netbeans.org/schema/exp1"ってこと。
        xmlns:tns="http://xml.netbeans.org/schema/exp1"は
        ちょうど今回作るスキーマのネームスペースをtnsとするってこと。tnsはtarget name spaceの略だ!
        -->
    <xsd:element name="exp">
    <!--
    schemaタグ以下にあるelementタグはルートになりうるタグだ!
    expタグが親になるってことのことよ。
    
    -->
        <xsd:complexType>
        <!--complexTypeは複合型のこと。対してsimpleType(単純型)ってのもある。素数のことではない。マザコンのアレでもない。-->
            <xsd:choice><!--choiceは選択である。これ以下の要素の中から1つ選べっちうかんじ。-->
                <xsd:element name="number"><!--numberタグ(数値タグ)の定義をする。-->
                    <xsd:simpleType><!--number方は単純型である-->
                        <xsd:restriction base="xsd:short"/><!--number型の型はshortだ!それ以外は許さん!-->
                    </xsd:simpleType>
                </xsd:element>

                <xsd:element name="add"><!--addタグ(足し算タグ)の定義をする-->
                    <xsd:complexType><!--addタグは式と式を入れられるから複合型とする-->
                        <xsd:sequence><!--addタグには2つ要素を連続で入れたい。そういう場合はsequence(連続)を使ったらよい。-->
                            <xsd:element ref="tns:exp"/><!--addタグにはexpタグが入るぜってこと。refは参照の意味で関数の再起呼び出しみたいなかんじ。-->
                            <xsd:element ref="tns:exp"/><!--もう一個書く-->
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
                <!--addタグコピッて、name=subとしただけで足し算の完成だ!-->
                <xsd:element name="sub">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element ref="tns:exp"/>
                            <xsd:element ref="tns:exp"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>

                <!--addタグコピッて、以下省略だ-->
                <xsd:element name="mul">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element ref="tns:exp"/>
                            <xsd:element ref="tns:exp"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>

                <!--addタグコピッて、以下しょうry)-->
                <xsd:element name="div">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element ref="tns:exp"/>
                            <xsd:element ref="tns:exp"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:choice>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>
<!--ってことで完成である-->

これだと、以下のようなxmlしか扱えなくて悲しいのです。

<exp>
  <add>
    <exp><number>1</number></exp>
    <exp>
      <add>
        <exp><number>1</number></exp>
        <exp><number>1</number></exp>
      </add>
    </exp>
  </add>
</exp>

とまぁ、expうざってことです。ということで疲れたのでこの辺で。
と、ぜんぜん、NetBeans使ってないんですけどっていう気もするんですけど、
XMLスキーマのexp.xsdとかいうファイルがあったら、
ソース、スキーマ、デザインってあって、スキーマのタブクリックしといて、あとは複合型とか選ぶと
なんか、それっぽいのができてって楽だったのでした。
なんとなく、こんなかんじにしたいっていうのが、やってけばそれなりの形になってくれてうれしいという。
それが、visual stdioだと、こう、したいのだけど、どうやったらなるのか謎のまま時が過ぎてってイライラ。
うー、解説になってない。墓穴ほってるな。
ってことで、とりあえず、触ってみてください。