高度なルール

by 3 contributors:

このセクションでは、さらに高度なルール構文について見ていきます。

完全なルール構文

これまでに説明したルールの構文でも、ある程度のデータソースまでは十分役に立ちますが、 データの表示にもっと複雑な方法が必要になることもあります。 実のところ、これまでの簡易なルール構文は、以下で説明する完全なルール構文の短縮形に過ぎません。 なお、簡易なルールの場合と同様に、完全なルールについても rule タグの中に置かれることになります。

完全なルールには、conditionsbindingsactionの 3 つのタグが含まれます。 ただし、bindings タグは常に必要なわけではありません。

conditions 要素は、与えられたリソースをマッチさせる条件を指定するために使用します。 ここには複数の条件が指定可能ですが、その場合は、すべての条件がマッチする必要があります。 (簡易なルール構文では、条件は rule 要素自身に直接設定していました)。

そして、条件にマッチするリソースに対しては、actions タグの中のコンテントが生成されることになります。 (簡易なルール構文では、生成するコンテントは rule タグ中に直接置かれていました)。

ルールの条件

テンプレートビルダーは、データソースからツリーやメニューなどの要素のコンテントを生成するとき、 まず最初に ref 属性が参照しているリソースを探して、 その後、そのリソースのすべての子リソースを走査していきます。 そのとき、各リソースに対して条件が適用され、 そのリソースに条件がマッチした場合には、actions 要素の中のコンテントが生成されることになり、マッチしない場合には、コンテントは生成されずに次に移ることになります。

content 要素

conditions 要素には 3 つの要素を含めることが可能です。 1 つめの要素は content で、これは常に存在する必要があり、かつ 1 つしか存在してはなりません。 この要素では、テンプレートビルダーがリソースを走査するときに渡される情報の置き場所を提供します。 具体的には、ここで条件のマッチ処理を行う際にルートリソースを参照できるよう保持しておく、変数の名前を指定することになります。 なお、ルートリソースとはテンプレートを含む要素の ref 属性で指定されるリソースのことです。

content 要素の構文は以下のようになります。

<content uri="?var"/>

このクエスチョンマークは、それに続くテキストが変数名であることを指示しています。 これにより、「var」変数を、条件の後の部分で利用することが可能になります。 もちろん、このとき変数名として好きな名称を指定することが可能です。

member 要素

2 つめの要素は member で、これは子リソースを走査する必要があることを示すために使用します。 この要素では、RDF でリスト記述するために使用する SeqBagAlt 要素のいずれかをコンテナとして参照します。

例えば、以下に一部だけを示す、RDF/XML で記述された都市の一覧があり、

<RDF:Seq about="http://www.xulplanet.com/rdf/weather/cities">
  <RDF:li resource="http://www.xulplanet.com/rdf/weather/city/Paris"/>
  <RDF:li resource="http://www.xulplanet.com/rdf/weather/city/Manchester"/>
  <RDF:li resource="http://www.xulplanet.com/rdf/weather/city/Melbourne"/>
  <RDF:li resource="http://www.xulplanet.com/rdf/weather/city/Kiev"/>
</RDF:Seq>

<RDF:Description about="http://www.xulplanet.com/rdf/weather/city/Paris">
  <cityset:name>Paris</cityset:name>
</RDF:Description>

.
.
.

この各都市を、ツリーの行に表示していきたいとすると、 member 要素は以下のように記述することになります。

<tree id="citiesTree" datasources="weather.rdf"
      ref="http://www.xulplanet.com/rdf/weather/cities"> 
  <template>
    <rule>
      <conditions>
        <content uri="?list"/>
        <member container="?list" child="?city"/>
      </conditions>
    <rule>
  <template>
</tree>

このテンプレートを展開する場合、まずテンプレートビルダーは、ref 属性の値の取得を行います。 そして、取得したリソース http://www.xulplanet.com/rdf/weather/cities は、 content タグで指定されている変数「list」に代入されます。 これにより、ルートリソースと関連するリソースは、この「list」変数を使用して取得することが可能になります。

次に、テンプレートビルダーは、member 要素の処理に移ります。 ここで、ビルダーは順次その要素の子要素を走査していくことになります。 このとき、リストを持つ親要素は container 属性で指定し、子は child 属性で指定します。 上記の例では、container 属性の値は、「list」変数を使用して指定しています。 このため、親には「list」変数の値、つまりルートリソース「http://www.xulplanet.com/rdf/weather/cities」が設定されることになります。 その結果、 「http://www.xulplanet.com/rdf/weather/cities」 にリストされるすべての子要素が走査されます。

上記の RDF では、リソース 「http://www.xulplanet.com/rdf/weather/cities」には 4 つの子があり、それぞれ異なる都市を指しています。 テンプレートビルダーは、子要素を繰り返しで処理し、そのとき対象の子要素と child 属性の値についてのマッチングが行われます。 ただし、この場合は、単に値を「city」変数 に設定するだけになります。 つまり、上記の記述によって、繰り返しの間、ビルダーに対象となる子リソースを「city」変数へ代入させることが可能です。

それ以外に条件は無いため、これらの 4 つのリソースは条件にマッチしたことになり、ビルダーはそれぞれに対してコンテントを生成します。 といっても、上記の例では生成すべきコンテントは設定されていません。 これは、もう少し後で追加する予定になっています。

triple 要素

3 つめの要素は triple です。 これは RDF データソースに、指定のトリプル (または言明) が存在するかどうかをチェックするために使用します。 トリプルとは、リソースにおけるプロパティのようなものと考えることができます。 例えば、ブックマークと その URL の間にはトリプルが存在して、 以下のようなグラフで表現されます

                                   URL
(mozilla.org のブックマーク)  ──────→  [www.mozilla.org]

これは、「mozilla.org のブックマーク」というブックマークと、「www.mozilla.org」の間には、URL プロパティによるトリプルが存在することを意味しています。 この表現において、最初の部分は「主語 (subject)」、矢印線は「述語 (predicate)」、最後の部分は「目的語 (object)」と呼ばれます。 これを、triple 要素で記述した場合、以下のように表現されます。

<triple subject="A Bookmark to mozilla.org"
        predicate="URL"
        object="www.mozilla.org"/>

これは、実際よりも若干単純化されていることに注意してください。 通常の場合、述語は XML の名前空間を含む URI になり、 主語は上記のようなブックマークのタイトルではなく、ブックマークのリソース id になります。 なお、実際にはブックマークのタイトルは、データソースの中で Name を述語とする別のトリプルに含まれてます。

triple 要素で、主語 (subject) と目的語 (object) については、変数を参照するように置き換えることができ、 その場合は変数に設定された値が使用されることになります。 ただし、変数の値がまだ定義されていない場合には、テンプレートビルダーは値をデータソースから探して変数に代入します。

例えば、都市のデータソースに天気予報の追加を行いたいとした場合、 以下のような条件を使用することになります。

<conditions>
  <content uri="?list"/>
  <member container="?list" child="?city"/>
  <triple subject="?city"
             predicate="http://www.xulplanet.com/rdf/weather#prediction"
             object="?pred"/>
</conditions>

テンプレートビルダーが上記を処理するとき、各都市のリソースを繰り返し処理していくところまでは先述の例と同じですが、 上記では、加えられた triple を処理するために、 RDF データソースから都市の天気予報についての言明が検索されて、 「pred」変数に予報が代入されることになります。 ビルダーは 4 つの都市のそれぞれに対してこれを繰り返します。 マッチ処理が済むと、ビルダーは予報が見つかった都市に対してのみコンテントの生成を行います。 つまり、都市に予報のリソースが存在しない場合は、条件は満たされていないことになるため、その都市についてはコンテントの生成は行われないことになります。 なお、簡易なルール構文を利用する場合と異なり、曖昧になることがないため、述語の先頭に「rdf:」を付ける必要がないことに注意してください。

また、下記の例のように、目的語 (object) の値を、インラインで直接指定することも可能です。

<conditions>
  <content uri="?city"/>
  <triple subject="?city"
             predicate="http://www.xulplanet.com/rdf/weather#prediction"
             object="Cloudy"/>
</conditions>

この例も以前のものと類似していますが、天気予報が「Cloudy (くもり)」の場合のみマッチするように指定している点が異なっています。 その結果、この条件は予報が「Cloudy」になっている都市に対してのみ満たされることになります。

また、さらなるマッチ条件が必要な場合は、トリプルを追加することも可能です。 例えば、上記の例にさらに温度と風速のチェックを追加する場合は、 単に追加するリソースのための別のトリプルを追加するだけで済みます。 この場合、条件はすべてのトリプルから値が得られた場合にのみマッチしたことになります。

以下の例は、新たにトリプルを追加して都市の名前をチェックします。 このとき、名前は「name」変数に代入されます。 この条件は、都市に名前があり、かつ予報があるときにのみマッチすることになります。

<conditions>
  <content uri="?list"/>
  <member container="?list" child="?city"/>
  <triple subject="?city"
             predicate="http://www.xulplanet.com/rdf/weather#name"
             object="?name"/>
  <triple subject="?city"
             predicate="http://www.xulplanet.com/rdf/weather#prediction"
             object="?pred"/>
</conditions>

コンテントの生成

ルールがマッチしたときに生成されるコンテントは、action 要素の中に指定します。 これは、ツリーの行やメニュー項目、といったリソースに応じて生成したいコンテントになります。 また、ここに置くコンテントからは、条件の部分で定義された変数を参照することが可能です。 したがって、上記の天気の例の場合、「name」と「pred」変数を使用することで、都市名や天気予報を表示させることが可能です。 なお、「list」や「city」変数も使用は可能ですが、 それらはテキストではなくリソースの情報が保持されているため、表示させても利用者に意味がある情報にはならないでしょう。

簡易なルール構文では、リソース対応にコンテントを生成する必要がある要素は、uri='rdf:*' を置くことで指定していましたが、 完全なルール構文の場合、uri 属性の値は、条件の部分で設定される変数を指定する必要があります。 通常、ここには、member 要素の child 属性で設定する変数を指定します。

完全なツリーの例

以下は、条件とアクションを含めた、ツリーを生成するための完全な例です。 使用する RDF ファイルは、別ファイルになっています : ソース RDF

var el = env.locale; 例 1 : ソース

<tree id="weatherTree" flex="1" datasources="weather.rdf"
      ref="http://www.xulplanet.com/rdf/weather/cities">
  <treecols>
    <treecol id="city" label="City" primary="true" flex="1"/>
    <treecol id="pred" label="Prediction" flex="1"/>
  </treecols>

  <template>
    <rule>
      <conditions>
        <content uri="?list"/>
        <member container="?list" child="?city"/>
        <triple subject="?city"
                predicate="http://www.xulplanet.com/rdf/weather#name"
                object="?name"/>
        <triple subject="?city"
                predicate="http://www.xulplanet.com/rdf/weather#prediction"
                object="?pred"/>
      </conditions>
      <action>
        <treechildren>
          <treeitem uri="?city">
            <treerow>
              <treecell label="?name"/>
              <treecell label="?pred"/>
            </treerow>
          </treeitem>
        </treechildren>
      </action>
    </rule>
  </template>
</tree>

このツリーは、2 つの列を持ち、 それぞれには、都市名 (name) の値と予報 (pred) の値が表示されます。

ツリーで dont-build-content フラグを利用する場合には、 content 要素を treeitem 要素に置き換えてください。

バインディングを追加する

ルールに含めることができる最後の要素は、bindings 要素で、その中には 1 つ以上の binding 要素を置くことが可能です。 このルールで指定するバインディングは、トリプルと同じ構文を持っており、機能もほぼ同じになります。 例えば、上記の天気の例に対しては、以下のようなバインディングを加えることが可能です。

<bindings>
  <binding subject="?city"
             predicate="http://www.xulplanet.com/rdf/weather#temperature"
             object="?temp"/>
</bindings>

このバインディングは、各都市に対して気温 (temperature) リソースを取得し、「temp」変数に代入します。 これはトリプルの挙動と似ていますが、バインディングは条件の判定に影響を与えない点が異なります。 つまり、都市の情報が表示されるためには、都市名と予報が存在することが必要であるのに対して、 気温についてはその必要はなく、リソースがある場合についてのみ「temp」変数に代入されて、アクションで利用可能になり、 都市に気温のリソースがない場合には、「temp」変数に空の文字列に設定されることになります。

次のセクションでは XUL 要素の状態を保存する方法について見ていきます。

ドキュメントのタグと貢献者

Contributors to this page: ethertank, Mgjbot, Morishoji
最終更新者: ethertank,