sequence と minOccurs, maxOccurs

2002年10月6日(日)更新


■複合型内容をもった複合型の例

たけち: 前回は複合型内容を持つ複合型の定義の基本的な考えを話したけれども、今回から具体的にどういう場合にどう書けばいいのかを説明していくことにするね。

さらら: は〜い (^ ^*

たけち: まずは前回の例題をもう一度見てみようね。

■複数の要素を子要素にもつXMLドキュメントの例
<poem pno="8">
    <poet>額田王</poet>
    <kana>
    熟田津尓 船乗世武登 月待者 潮毛可奈比沼 今者許藝乞菜
    </kana>
    <yomi>
    熟田津に船乗りせむと月待てば潮もかなひぬ今は漕ぎ出でな
    </yomi>
</poem>

たけち: このXMLドキュメントのDTDは次のようだったね。

■上記サンプルのDTD
<!ELEMENT poem (poet?, kana, yomi)>
<!ATTLIST poem pno CDATA #REQUIRED>
<!ELEMENT poet (#PCDATA)>
<!ELEMENT kana (#PCDATA)>
<!ELEMENT yomi (#PCDATA)>

さらら: あっ、そうだったわね。(^ ^;

たけち: これに相当するXML Schemaは、つぎのようだったね。

さらら

■上記poemのXML Schema
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="poem" type="PoemType"/>

<xsd:complexType name="PoemType">
    <xsd:sequence>
    <xsd:element ref="poet" minOccurs="0"/>
    <xsd:element ref="kana" />
    <xsd:element ref="yomi" />
    </xsd:sequence>

<xsd:attribute name="pno" type="xsd:positiveInteger" use="required" />
</xsd:complexType>

<xsd:element name="poet" type="xsd:string" />
<xsd:element name="kana" type="xsd:string" />
<xsd:element name="yomi" type="xsd:string" />

</xsd:schema>

さらら: えぇ。

たけち: この中で、

    <xsd:sequence>
    <xsd:element ref="poet" minOccurs="0"/>
    <xsd:element ref="kana" />
    <xsd:element ref="yomi" />
    </xsd:sequence>


というのは、一連の、一続きの、順番に、とかいった意味なんだ。

さらら: 英語のsequenceって、そういう意味だわね。

たけち: DTDの

    (poet?, kana, yomi)

の部分に相当する部分なんだ。これは必ず、
    poet → kana → yomi
の順番で出現しないといけないという意味だね。

たけち

さらら: えぇ、そうね。

たけち: ただし、poetだけは、"?"がついていてオプション扱いになっているから、
    kana → yomi
という順番でもいいね。でも、
    kana → poet → yomi だとか     yomi → kana
のような順番は許されないという意味なんだ。DTDではこの関係を「,」を使って表していたけれど、XML Schemaではxsd:sequenceという要素で表すわけなんだよ。


■ref属性で要素名を参照

さらら: これはわかるわ。とにかく順番どおり、というのは一番基本よね。このxsd:sequenceという要素の中で、
<xsd:element ref="要素名" /> という形で"要素名"を持つ要素を参照するわけね!!

たけち: そうだね。ここで、xsd:element要素で、要素名を参照している属性がrefだということに気をつけてね。ここでは、既にxsd:string型の値をとるpoet, kana, yomiといった要素の宣言がすんでいて、それを参照しているからrefなんだ。
実はここにref属性ではなくて、name属性を使って、含まれている要素を定義することはできるんだけれど、refを使う場合とnameを使う場合とでは若干意味が違ってくるんだよ。その話は後でするから、ここでは単に、既に宣言した要素を参照するref属性だというふうに覚えておこうね。

さらら: ふ〜ん、そうなの。

さらら


■パーティクル(particle)

たけち: それから、このxsd:sequenceや後で説明するxsd:choicexsd:allの内容を構成する子要素になるのがパーティクルと言われるものなんだ。このパーティクルの代表がこの例にあるように、xsd:elementなんだよ。
その他にxsd:sequenceの内容になる「パーティクル」としては、xsd:sequence自身もモデルグループであると同時にパーティクルにもなるし、そして後で説明するxsd:choice、そしてxsd:groupという名前付きグループの参照もパーティクルになるんだよ。

さらら: えっ、たけち。もう一回説明して... (^ ^; 突然たくさん新しい言葉が出てきたからわからなかったの (^ ^;

たけち: あ、ごめん。一度に言い過ぎたね (^ ^; 要するにxsd:sequenceの内容になるものとしては、xsd:elementが代表的だけれど、それ以外にもいろいろあるよ、ということなんだよ。これらのいろいろなパーティクルについては、これから順々に説明していくから、今は心配しないでね。

さらら: うん、わかったわ。それで話が変わるけれども minOccurs="0" というのが、DTDの「?」に相当するものなのね。

さらら


■出現頻度(DTDとXML Schema)

たけち:そう。ここでは結果的にそういうことになるね。ただ、DTDとXML Schemaでは出現頻度を制御する仕組みの考え方が、基本から少し違うから、それをちょっと説明するね。まずDTDでは出現頻度を決める方法は「?」以外に何があったかな?

さらら: え、え〜っと "*" と。。。(^ ^;

たけち: 以下の4種類だよね。

たけち

DTDでの出現頻度の指定

さらら: あ、そうだったわね (^ ^;

たけち:さて、これを見てわかるように、DTDで設定することができた出現頻度の制御というのは「0」か「1」か「無限大」のどれかなんだ。例えば、「必ず3回出現」とか「10回以上、20回以下の出現」とかいう指定の仕方はDTDでは無理だったんだね。

さらら: あ、そうよね。

たけち: そこでXML Schemaでは、出現頻度の最低値と最高値の2つを指定する形式にしたんだ。具体的にはminOccursという属性に出現頻度の最低値を、maxOccursという属性に出現頻度の最高値を指定するようにしたんだよ。例えば、さっきの例だと、

たけち

    minOccurs="3" maxOccurs="3" → 「必ず3回出現」
    minOccurs="10" maxOccurs="20" → 「10回以上、20回以下の出現」

というふうに指定するんだ。


■minOccurs, maxOccurs

さらら: へぇ〜、指定の仕方がきめこまかくなったのね。

たけち:ちなみにこの書き方を先ほどのDTDの表記法と対比させると、以下のようになるよ。

さらら

DTDに対応するXML Schemaでの出現頻度の指定

さらら: unboundedって?

たけち:このunboundedというのは、無制限とか無限大とかいった意味になるんだよ。

さらら: なるほど。

たけち: だから本来、最初に示した例題を厳密にきちんと書くと、こういう書き方になるんだ。

■XML Schemaで、出現頻度をきちんと書くと
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="poem" type="PoemType"/>

<xsd:complexType name="PoemType">
    <xsd:sequence minOccurs="1" maxOccurs="1">
    <xsd:element ref="poet" minOccurs="0" maxOccurs="1" />
    <xsd:element ref="kana" minOccurs="1" maxOccurs="1" />
    <xsd:element ref="yomi" minOccurs="1" maxOccurs="1" />
    </xsd:sequence>
<xsd:attribute name="pno" type="xsd:positiveInteger" use="required" />
</xsd:complexType>

<xsd:element name="poet" type="xsd:string" />
<xsd:element name="kana" type="xsd:string" />
<xsd:element name="yomi" type="xsd:string" />

</xsd:schema>

さらら: そっか〜。こうなるのね。でも最初はこんな書き方はしていなかったわ。

たけち: そうだね。というのは、これを見てもわかるけれど、とにかく圧倒的に多く出てくるのは、値が1の場合だよね。DTDでも無指定の場合は「必ず1回のみ出現」になっていたけれど、XML Schemaでも値が1の場合は、こういうminOccurs属性やmaxOccurs属性は省略してもよいことになっているんだ。
逆にminOccurs属性やmaxOccurs属性が使われる場所で、それが省略されているということは、これは実はデフォルトで1という値になっているということだよ。だから、最初の書き方は省略した書き方で、省略されているからその値は1だということになるね。

さらら: あ、なるほど。それからよく見たら、xsd:sequence自体にもこのminOccurs属性やmaxOccurs属性が使われているわ。

たけち: そうなんだよ。xsd:elementだけでなくて、xsd:sequence自体も、minOccurs属性やmaxOccurs属性で出現頻度を決められることも知っておこうね。
だからDTDでいうと、

   <!ELEMENT poem (poet?, kana, yomi)+>
   <!ELEMENT poet (#PCDATA)>
   <!ELEMENT kana (#PCDATA)>
   <!ELEMENT yomi (#PCDATA)>

に相当するXML Schemaは、次のような書き方もできるんだよ。

さらら

■minOccurs="1", maxOccurs="1"を省略して書く
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="poem" type="PoemType"/>

<xsd:complexType name="PoemType">
    <xsd:sequence maxOccurs="unbounded">
    <xsd:element ref="poet" minOccurs="0" />
    <xsd:element ref="kana" />
    <xsd:element ref="yomi" />
    </xsd:sequence>
</xsd:complexType>

<xsd:element name="poet" type="xsd:string" />
<xsd:element name="kana" type="xsd:string" />
<xsd:element name="yomi" type="xsd:string" />

</xsd:schema>

さらら: なるほどねぇ。

たけち: こういう書き方をすると、次のようなXMLデータが合ってくるようになるね。

■複数の要素を子要素にもつXMLドキュメントの例
<poem>
    <poet>額田王</poet>
    <kana>
    熟田津尓 船乗世武登 月待者 潮毛可奈比沼 今者許藝乞菜
    </kana>
    <yomi>
    熟田津に船乗りせむと月待てば潮もかなひぬ今は漕ぎ出でな
    </yomi>
    <poet>天智天皇</poet>
    <kana>
    渡津海乃 豊旗雲尓 伊理比紗之 今夜乃月夜 清明己曽
    </kana>
    <yomi>
    海神の豊旗雲に入日さし今夜の月夜さやけくありこそ
    </yomi>
</poem>


■minOccurs属性、maxOccurs属性、属性宣言のuse属性

さらら: こういう感じになるのね。

たけち: あと、このminOccurs属性、maxOccurs属性と、属性宣言に使われるuse属性の対比についても覚えておこうね。

さらら: え、属性宣言のuse属性って全然違うものじゃないの?

たけち: 一見そう見えるかもしれないけれど、実は以下のように対比できるんだ。そしてこう対比させておくと、「出現制約」という大事な考え方もわかりやすくなってくるから、覚えておこうね。

minOccurs属性、maxOccurs属性、属性宣言のuse属性

さらら: ふ〜ん、そう言われればこういう関係になりそうね。

たけち: sequenceの基本的使い方についてはこれでおしまい。次回はsequenceと並んでよく使うchoiceについて説明するね。

さらら: あっ、はい!

次のchoiceにつづきます 。。。。 (^ ^*

さらら


XMLスキーマのコーナーは、TAKABEさま(XSLTの遊び部屋)の全面的なご協力をいただいて作成しています。