連想配列
伝統的なHTMLページを見てみると、<select>要素は通常、連想配列の使用を前提として機能しています。
colors = {rd : 'red', or : 'orange', ye : 'yellow',
gn : 'green', bu : 'blue', vi : 'violet'}
<select value="rd" name="colorkey">
<option value="rd">red</option>
<option value="or">orange</option>
<option value="ye">yellow</option>
<option value="gn">green</option>
<option value="bu">blue</option>
<option value="vi">violet</option>
</select>
各オプションのテキストブロックには「ラベル」(配列の各アイテムの右側の部分)が含まれ、value属性には各アイテムの「名前」が指定されます。大事なのは、選択コントロールでアイテムが選択されてそのアイテムの「ラベル」がドロップダウンリストに表示されているときは、それに対応する「名前」(つまり各オプションのvalue属性値)がコントロールの値になることです。同様の式はXFormsでも使用できますが、次のように関連付けがもう少し明確に定義されます。
<xf:select1 ref="colorkey"> <xf:item> <xf:label>red</xf:label> <xf:value>rd</xf:value> </xf:item>
こうした概念は当然ほとんどのコンピュータ言語にとって基本的なものですが、次のように若干異なるモデルをXFormsで実現しようとした場合は、話が少々複雑になります。
<xf:model id="datamodel"> <xf:instance id="data"> <data> <colorkey>rd</colorkey> </data> </xf:instance> <xf:instance id="colors"> <colors> <color name="rd" label="red"/> <color name="or" label="orange"/> <color name="ye" label="yellow"/> <color name="gn" label="green"/> <color name="bu" label="blue"/> <color name="vi" label="violet"/> </colors> </xf:instance> </xf:model> <xf:select1 ref="colorkey"> <xf:itemset nodeset="instance('colors')//color"> <xf:label ref="@label"/> <xf:value ref="@name"/> </xf:item> </xf:select1>
この場合、連想配列(ここではcolor要素の名前とラベルとして定義されています)は、選択コントロールから独立したdataインスタンスに含まれています。この場所は、HTMLを使ってきた人にとっては少し変に感じられます。HTMLでは、配列はコントロールの中にあります。しかし、XFormsのコンテンツを扱う場合にはこれが普通です。XFormsのコンテンツでは、コントロールは既存のデータ構造にビューだけを提供するという前提を基礎にしています。この連想配列は、特定のデータプロパティに対してどのような値が有効かを決定するための制約を定義するスキーマによく似た働きをします。
ここまではよいでしょう。列挙されたリストを使ったスキーマは、スキーマ(特にXSDスキーマ)の使用法としてはごく一般的です。ではさらに進んで、制約リストを外部XMLファイルに移し、そこから取得するという方法を考えてみましょう。
<xf:model id="datamodel"> <xf:instance id="data"> <data> <colorkey>rd</colorkey> </data> </xf:instance> <xf:instance id="colors" src="colors.xml"/> </xf:model> <xf:select1 ref="colorkey"> <xf:itemset nodeset="instance('colors')//color"> <xf:label ref="@label"/> <xf:value ref="@name"/> </xf:item> </xf:select1>
概念的には、このアプローチはそれほど飛躍ではありません。ただし、もっと広い視野で何が起きているのか注意してみてください。色のリストがスキーマの一部であると見るならば、単にそのスキーマが分散したというだけの話です(少なくともスキーマの一部が、残りのスキーマの範囲外に存在しています)。繰り返しますが、このアプローチはそれほど変わったものではありません。ほとんどのスキーマでは何らかのモジュール化が行われているのが普通であり、モジュール化によってスキーマが分解され、いくつかの場所に分散されます。これでスキーマをネットワーク上で利用できるようになりますが、まだ制約があり静的です。
では、もう一歩進んでみましょう。
<xf:model id="datamodel"> <xf:instance id="data"> <data> <colorkey>rd</colorkey> </data> </xf:instance> <xf:instance id="colors" src="''colors.xq''"/> </xf:model> <xf:select1 ref="colorkey"> <xf:itemset nodeset="instance('colors')//color"> <xf:label ref="@label"/> <xf:value ref="@name"/> </xf:item> </xf:select1>
この例では、ソースをXMLドキュメントから、REST呼び出しのXQueryの結果に変更しています(これを別のサーバー言語に置き換えても考え方は同じです)。また、それにともなって重大な変化が起きています。このクエリは、ある動的なプロセスが直前に発生することを前提としています。すなわち、このモデルが持つことのできる列挙はもはや静的ではないということです。たとえば、colors.xqがクレオラ製の(何億兆もの色数が入っている)クレヨン箱の中から、ランダムに12色のセットを取り出すとします。さらに、1日くらいで最初のセットの約5パーセントの色がなくなり、同じ分だけ追加されるとします。要するに、色セットの列挙リストを用意することはできても、その色セットの静的な定義はないという状況です。これは、XSDではモデル化できません。
例が不自然に思えるかもしれませんが、これは前述したNordstromの店舗の問題とまったく同じであり、実際にWebアプリケーションの構築でよく見られるようになっている問題です。では、ただの空白テキストフィールドと制約のないセットにするべきなのかというと、そうではありません。このようなセットは未知のものではなく、いつでも検証可能ですが、動的な性質も備えているということです。このような検証は時間によって結果が変わってきます。その色は使えるかどうか、その店舗は営業中かどうか(閉まっていないか)という検証を行うには、時間をパラメータとして考慮しなければなりません。実世界の物事はこのように動いており、この事実を便宜上の都合で無視すると、結局はうまく機能しないモデル(およびアプリケーション)ができてしまいます。
