oneOrMore 要素
1回以上の繰り返しを定義する要素
- 子要素に記述される一聯のパターンに関し、それらのパターンが1回以上繰り返して出現することを指示する要素です。
- XML では、主に要素の中身の定義に対して用います。
- attribute要素 の直截の親要素として用た場合、その属性は必須属性と見倣されます(attribute要素 を element要素 直下に記述した場合と同様)。ただし、複数の同名の属性を記述出来るわけではないので、注意してください。
- attribute要素 の子孫要素としては用いることが出来ません。
- grammar 要素の直下には置いてはなりません。
- スキーマのルート要素に用いることが出来ます。ただし、そのスキーマは単独では用いることは出来ず、 externalRef 要素の参照先としてのみ利用できます。
- 要素名に大文字が混じっていますので、記述には注意してください。
属性
lang:occurs 属性
名前空間 lang に属する属性です。繰り返し処理の回数を、事前に設定してください。
- decode : 指定された回数だけ、繰り返し処理を実行します。
- encode : 指定された回数だけ、繰り返し処理を実行します(encode 時は必須です)。
lang:occured 属性
名前空間 lang に属する属性です。oneOrMore の処理の後に設定されます。
- decode : 繰り返し数の解析結果が、指定された変数に代入されます。
- encode : 指定できません。
制約
- optional、oneOrMore、zeroOrMore を入れ子にできる最大数は、「32」です。
- ref 要素を中身にし、マクロを参照することが出来ます。 ただし、ソースコードの生成前に、define/ref が展開されている必要があります。
- lang:occurs 属性と、lang:occured 属性を同時に指定することはできません。 どちらか一方を必ず指定してください。
- lang:occurs 属性に 1 未満の値を指定することはできません。エラーとなります。
子ノード
- 複数の コンテナ もしくは サブコンテナ を子要素に持つことが出来ます。
- interleave要素, optional要素, zeroOrMore要素 などを子に持つことも可能です。
使用例
例 1: mapping の例 (XML-XML syntax)
以下のパターンは、1 バイト以上のバイナリデータにマッチします。 変数 n に、バイト長を対応させています。
- decode の例
-
<oneOrMore lang:occured="n"> <dat:byte length="1"> <lang:value-of select="i"> <data type="int"/> </lang:value-of> </dat:byte> <callFunction expr="pushValue( i );"/> </oneOrMore>
- encode の例
-
<oneOrMore lang:occurs="n"> <callFunction expr="i = popValue();"/> <dat:byte length="1"> <lang:value-of select="i"> <data type="int"/> </lang:value-of> </dat:byte> </oneOrMore>
decode では、繰り返し数の解析結果が変数 n に代入されます。また、 encode では、変数 n で指定された回数分繰り返しが行われます。
例 2: mapping の例 (XML-language syntax)
例 1 は、以下のように書き直すことができます。 しかし、記述方法については、まだ決定していません。
- decode の例
-
<oneOrMore> <dat:byte length="1"> <callFunction expr="pushValue( <data type="int"/> );"> </dat:byte> n = </oneOrMore>;
- encode の例
-
<oneOrMore> = n; <dat:byte length="1"> <data type="int"/> = <callFunction expr="popValue();"/> </dat:byte> </oneOrMore>
例 3: JAVA での mapping の例 (XML-language syntax)
JAVA には Interator や Collection など集合を取り扱うのに 便利なクラスがそろっています。これらを使用することもできます。
- Iterator を用いた encode
-
<oneOrMore> <lang:var class="Byte" name="b" interator="iterator"> <dat:byte length="1"> <data type="byte"/> = b.byteValue(); </dat:byte> </lang:var> </oneOrMore>
- List を用いた encode
-
<oneOrMore> <lang:var class="Byte" name="b" collection="list"> <dat:byte length="1"> <data type="byte"/> = b.byteValue(); </dat:byte> </lang:var> </oneOrMore>
- List を用いた decode
-
<oneOrMore> <dat:byte length="1"> list.add( new Byte(<data type="byte"/>) ); </dat:byte> </oneOrMore>
が、美しい記法ではないですね。
考えてみよう!
その 1: 連続する oneOrMore要素
連続する oneOrMore要素 の中身を、一つの oneOrMore要素 の中身としてまとめることは出来ません。以下に、その例を示します。
- 例1
-
<oneOrMore> <ref name="a"/> </oneOrMore> <oneOrMore> <ref name="b"/> </oneOrMore>
- 例2
-
<oneOrMore> <ref name="a"/> <ref name="b"/> </oneOrMore>
例1では、「aが1回以上出現した後、bが1回以上出現するパターン (aa…bb…)」であるのに対し、例2では、「aとbが、この順番を保持したまま1回以上出現 (abab…)」となります。
その 2: 出現順番に関して
- choice要素, interleave要素 の子要素でない場合、定義の出現順位は保持されます。
- oneOrMore要素 の子要素の中で、choice要素, interleave要素 が存在しない部分は、定義の出現順位は保持されます。
参考文献
- James Clark and Makoto Murata, ISO/IEC FDIS 19757-2 Document Schema Definition Language (DSDL) -- Part 2: Regular-grammar-based validation -- RELAX NG
- 古林 寛, 「oneOrMore要素 @ ぽかぽか RELAX NG 工房」