xulfr.org

6.9 Règles avançées

Écrit par Neil Deakin. Traduit par Julien Etaix (22/07/2004).
Page originale : http://www.xulplanet.com/tutorials/xultu/advrules.html xulplanet.com

Ce paragraphe décrit la syntaxe des règles les plus complexes.

La syntaxe de règle complète

La syntaxe des règles décrites jusqu'ici est utile pour certaines sources de données, mais l'on a parfois besoin d'afficher les données d'une manière plus sophistiquée. La syntaxe de règle simple n'est en fait qu'un raccourci pour la syntaxe de règle complète qui est décrite ci-dessous. Comme pour la syntaxe de règle simple, la règle complète est placée entre des balises rule.

Une syntaxe de règle complète contient trois balises filles, une balise conditions , une balise bindings et une balise action , bien qu'une balise bindings ne soit pas toujours nécessaire.

L'élément conditions spécifie le critère qui doit correspondre à une ressource donnée. Vous pouvez spécifier le nombre de conditions, qui doivent toutes correspondre à la ressource donnée. En utilisant la syntaxe de règle simple, les conditions sont directement situées sur l'élément rule.

Si les conditions correspondent à une ressource, le contenu placé entre les balises action est activé. Dans la syntaxe de règle simple, le contenu est directement placé dans la balise rule.

Conditions d'une règle

Lorsque qu'un arbre, un menu ou tout autre élément avec une source de donnée génère son contenu, le générateur de modèle cherche en premier la ressource marquée par l'attribut ref. L'opération est ensuite répétée pour l'ensemble des ressources filles. Il compare chaque ressource aux conditions. Si celles-ci sont vérifiées, le contenu de l'élément action est généré pour cette ressource. Si elles ne sont pas vérifiées, rien n'est généré.

L'élément conditions contient trois sous éléments. Le premier est l'élément content qui doit toujours être présent une fois seulement. Il sert de marqueur lorsque le générateur de modèle parcourt les ressources. Il indique le nom de la variable dans laquelle est placée une référence à la ressource racine pendant que les conditions sont analysées. La ressource racine est celle indiquée par l'attribut ref dans l'élément contenant le modèle.

La syntaxe d'un élément content est la suivante :

<content uri="?var"/>

La point d'interrogation indique que le texte qui suit est une variable. Vous pouvez alors utiliser la variable var dans le reste des conditions. Bien entendu, vous pouvez appeler la variable comme vous le voulez.

L'élément suivant est l'élément member, qui est utilisé pour parcourir un ensemble de ressources filles. En termes RDF, c'est comparable à Seq, Bag ou Alt. Disons que vous avez une liste de villes comme dans le code RDF/XML suivant :

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

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

.
.
.

Vous voulez afficher une ligne dans une arborescence pour chaque ville. Pour accomplir cela, utilisez l'élément member comme ceci :

<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>

Le générateur de modèle commence par récupérer la valeur de l'attribut ref, qui dans ce cas est http://www.xulplanet.com/rdf/weather/cities. Cette ressource va être mise dans la variable list comme il est indiqué par la balise content. On peut alors obtenir les ressources associées à la ressource racine en utilisant la variable list.

Le générateur de modèle s'intéresse ensuite à l'élément member. Cela force le générateur à itérer sur les fils d'un élément. Le parent est indiqué par l'attribut container et les fils par l'attribut child. Dans l'exemple ci-dessus, la valeur de l'attribut container est la variable list. Ainsi le parent sera la valeur de la variable list, qui a la valeur de la ressource racine http://www.xulplanet.com/rdf/weather/cities. L'effet induit va être de parcourir à travers la liste des fils de 'http://www.xulplanet.com/rdf/weather/cities'.

Si vous regardez en détail le RDF ci-dessus, la ressource 'http://www.xulplanet.com/rdf/weather/cities' a quatre filles, une pour chaque ville. Le générateur de modèle parcourt chacune d'elle, comparant la fille avec la valeur de l'attribut child. Dans le cas présent, celui-ci contient la valeur city. Donc le générateur va donner à la variable city la valeur des ressources filles au fur et à mesure.

Comme il n'y a pas d'autres conditions, la condition correspond à chacun des quatre ressources et le générateur va créer du contenu pour chacune des quatre. Bien sûr, l'exemple ci-dessus n'a aucun contenu. On l'ajoutera par la suite.

L'élément suivant est l'élément triple. Il est utilisé pour vérifier l'existence d'un triplet (ou assertion) dans la source de donnée du RDF. Un triplet est comme la propriété d'une ressource. Par exemple, un triplet existe entre un marque-page et son URL associée. Cela peut-être exprimé ainsi :

Un marque-page vers mozilla.org  ->  URL  ->  www.mozilla.org

Cela signifie qu'il existe un triplet entre le marque-page Un marque-page vers mozilla.org et www.mozilla.org par la propriété URL. La première partie est appelée le sujet, la seconde, le prédicat, et la dernière, l'objet. Exprimé en tant qu'élément triple, il serait ainsi :

<triple subject="Un marque-page vers mozilla.org"
           predicate="URL"
           object="www.mozilla.org"/>

Cela a été un peu simplifié par rapport au code réel. Le prédicat devrait normalement inclure les espaces de nom (namespace), et le sujet devrait être l'identifiant ressource du marque-page, et non pas le titre du marque-page comme ici. En fait, le titre du marque-page devrait être un autre triplet dans la source de donnée qui utiliserait le prédicat 'nom'.

Vous pouvez remplacer le sujet et l'objet dans l'élément triple avec des références aux variables, auquel cas les valeurs seront substituées aux variables. Si aucune valeur n'est définie pour une variable, le générateur de modèle va attribuer la valeur de la source de donnée à la variable.

Disons par exemple, que l'on veuille ajouter une prédiction météo à la source de données des villes. Les conditions suivantes peuvent être utilisées :

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

Le générateur de modèle va parcourir chaque ville comme précédemment. Lorsqu'il va en arriver au triplet, il va s'intéresser aux assertions de la source de données RDF pour une prédiction météo. On attribue à la variable pred la prédiction météo. Le générateur va répéter cette opération pour chacun des quatre villes. Une comparaison a lieu et le générateur va crée du contenu pour chaque ville qui a une prédiction météo associée. Si la ville n'a pas de ressource de prédiction, la condition ne correspond pas et aucun contenu ne sera crée pour cette ville. Remarquez que vous n'avez pas besoin de mettre 'rdf:' au début du prédicat, ceci est sous-entendu.

On peut aussi remplacer l'attribut object avec une valeur statique. par exemple :

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

Cet exemple est similaire mais nous spécifions que nous voulons une comparaison qui s'effectue sur Nuageux. Le résultat obtenu est que la condition ne va s'appliquer que pour les villes dont la prédiction météo est Nuageux.

On peut ajouter davantage de triplet pour réaliser plus de comparaisons. par exemple, dans l'exemple ci-dessus, on peut également vouloir vérifier la température et la vitesse du vent. Pour cela, il suffit d'ajouter un autre triplet qui vérifiera les ressources supplémentaires. La condition va correspondre si et seulement si l'intégralité des triplets retournent des valeurs.

L'exemple ci-dessous va vérifier un triplet supplémentaire concernant le nom de la ville. Il lui sera attribué une variable name. La condition va correspondre si la ville a à la fois un nom et une prédiction météo.

<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>

Générer du contenu

Le contenu à générer pour une règle est spécifié dans l'élément action. Cela peut être le contenu des lignes d'un arbre, les items de menu ou quoi que vous vouliez générer. A l'intérieur du contenu, vous pouvez vous référer aux variables qui ont été définies dans les conditions. Ainsi, dans l'exemple météo ci-dessus, vous pouvez utiliser les variables name ou pred pour afficher la ville ou la prédiction météo. Vous pouvez aussi utiliser les variables list ou city mais elles contiennent des ressources et non du texte, donc elles n'auront pas de sens pour les utilisateurs.

Dans la syntaxe de règle simple, on utilise la syntaxe uri="rdf:*" pour indiquer l'emplacement où le contenu doit être généré. Dans la syntaxe de règle complète, on donne la valeur de l'attribut uri à une variable que l'on a utilisé dans les conditions. Normalement, ce sera la variable assignée à l'attribut child de l'élément member.

L'exemple suivant montre un arbre complet avec des conditions et une action. Vous pouvez consulter le fichier RDF séparément ( Source RDF).

Exemple 6.9.1  Source Voir :

<tree id="weatherTree" flex="1" datasources="weather.rdf"
      ref="http://www.xulplanet.com/rdf/weather/cities">
  <treecols>
    <treecol id="city" label="Ville" primary="true" flex="1"/>
    <treecol id="pred" label="Prédiction Météo" 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>

Deux colonnes apparaissent dans cet arbre, l'une qui affiche la valeur de "nom" pour chacun ligne, et l'autre qui affiche le résultat de la prédiction météo.

Si vous utilisez le marqueur dont-build-content (ne-pas-générer-de-contenu) sur un arbre, remplacez l'élément content par un élément treeitem

Ajouter des liens supplémentaires

Le dernier élément que vous pouvez ajouter à l'intérieur d'une règle est l'élément bindings. À l'intérieur de celui-ci, vous pouvez mettre un ou plusieurs élément binding. Un lien dans une règle a la même syntaxe qu'un triplet et remplit quasiment la même fonction. Par exemple, dans l'exemple météo précédent, on peut ajouter le lien suivant :

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

Le lien va prendre la ressource "température" de chaque ville et l'attribuer à la variable temp. C'est tout à fait similaire à ce qu'un triplet accomplit. La différence se situe dans le fait qu'un lien n'est pas examiné lorsque quand les conditions sont vérifiées. Cela veut dire que chaque ville doit avoir un nom et une prédiction météo associée pour être affichée, mais cela n'a aucune importance si elle n'a pas de température. Cependant, si elle en a une, la valeur sera attribuée à la variable temp afin qu'elle soit utilisée dans une action. Si une ville n'a pas de température, la variable temp sera une chaîne de caractère vide.


Par la suite, nous verrons comment ajouter des gestionnaires d'évènements dans les éléments XUL.