7 Les expressions XPath dans XForms

XForms emploie le langage XPath pour accéder aux nœuds de donnée d'instance dans les expressions de liaison, pour exprimer des contraintes et pour définir des calculs. Les expressions XPath dont la syntaxe est invalide, y compris les tentatives d'appel à des fonctions non définies, produisent une exception (4.5.4 L'événement xforms-compute-exception), à l' exception des expressions de liaison qui produisent une autre exception (4.5.1 L'événement xforms-binding-exception).

7.1 Les types de données XPath

Les types de données XPath ne s'utilisent que dans les expressions de liaison et les expressions calculées. XForms utilise les types de données XPath boolean, string, number et node-set. On prévoit qu'une version future de XForms utilisera le langage XPath 2.0, lequel gère les types de données du schéma XML.

7.2 La chaîne de fonctionnalité de l'appel de méthode hasFeature

Dans cette version de la spécificaton XForms, la chaîne de fonctionnalité d'appel de la méthode hasFeature de l'interface DOMImplementation [DOM2 Core] est "org.w3c.xforms.dom" et la chaîne de version est "1.0".

7.3 Les données d'instance

Le processeur XForms tient à jour l'état de chaque élément model dans une structure interne, appelée données d'instance, qui est conforme au modèle de données XPath [XPath 1.0]. Les processeurs XForms qui prennent en charge le modèle DOM doivent fournir un accès DOM à ces données d'instance via l'interface définie ci-dessous.

Remarque :

Les données d'instance ont toujours un seul élément racine et correspondent, de ce fait, à un document DOM.

La définition IDL de cette interface est la suivante :

#include "dom.idl"
pragma prefix "w3c.org"
module xforms {
  interface XFormsModelElement : dom::Element {
    dom::Document getInstanceDocument(in dom::DOMString instanceID)
      raises(dom::DOMException);
    void rebuild();
    void recalculate();
    void revalidate();
    void refresh();
  };
};

7.3.1 La méthode getInstanceDocument()

Cette méthode renvoie un document DOM qui correspond aux données d'instance associées à l'élément instance, lequel document contient un ID correspondant au paramètre instance-id. Si aucune donnée d'instance ne correspond, alors une exception DOMException est générée.

7.3.2 La méthode rebuild()

Cette méthode indique au processeur XForms de reconstruire toutes les structures de données internes utilisées pour le suivi des dépendances de calcul dans le modèle XForms en question. Elle ne prend aucun paramètre et ne génère aucune exception.

7.3.3 La méthode recalculate()

Cette méthode indique au processeur XForms de réaliser un recalcul complet du modèle XForms en question. Elle ne prend aucun paramètre et ne génère aucune exception.

Remarque :

L'invocation par un script de la méthode recalculate() n'équivaut pas forcément à l'exécution du gestionnaire de l'action recalculate. Bien que le script soit censé avoir modifié les données d'instance avant d'invoquer recalculate(), les mutations du DOM ne sont pas mises en cache. De ce fait, un recalcul complet est indispensable pour assurer que les changements nécessaires aient été réalisés à travers le modèle XForms.

7.3.4 La méthode revalidate()

Cette méthode indique au processeur XForms de réaliser une revalidation complète du modèle XForms en question. Elle ne prend aucun paramètre et ne génère aucune exception.

7.3.5 La méthode refresh()

Cette méthode indique au processeur XForms de réaliser un rafraîchissement complet des commandes de formulaire liées aux nœuds d'instance dans le modèle XForms en question. Elle ne prend aucun paramètre et ne génère aucune exception.

7.4 Le contexte d'évaluation

Dans le langage XForms, les expressions XPath appellent des données d'instance abstraites (au moyen de la partie path de XPath) au lieu d'un document XML concret. Dans cette spécification, on appelle cette référence une expression de liaison. Chaque expression XPath opère dans un contexte d'évaluation. Les règles suivantes servent à déterminer un contexte d'évaluation lors de l'évaluation d'une expression XPath dans un environnement XForms :

  1. Le nœud de contexte des éléments de liaison les plus externes est le nœud d'élément de niveau supérieur, ou le nœud seul renvoyé par /*. Tout élément admettant explicitement un attribut d'expression de liaison est un élément de liaison. Un élément de liaison est le plus externe lorsque l'ensemble de nœuds renvoyé par l'expression XPath ancestor::* ne comprend aucun nœud d'élément de liaison ;

  2. Le nœud de contexte des éléments de liaison qui ne sont pas les plus externes est le premier nœud de l'expression de liaison de l'élément englobant immédiat. Un élément est englobant immédiat lorsque c'est le premier nœud d'élément de liaison dans l'ensemble de nœuds renvoyé par l'expression XPath ancestor::*. C'est ce qu'on appelle aussi une résolution dans la visibilité ;

  3. Le nœud de contexte réside toujours dans le modèle de contexte, que l'on détermine en choisissant la première définition qui s'applique dans la liste suivante :

    1. Si un attribut model est présent sur l'élément de liaison, alors il détermine le modèle de contexte 

    2. Si l'élément de liaison a un élément de liaison englobant immédiat, alors le modèle de contexte de celui-ci est utilisé ;

    3. On utilise le premier modèle dans l'ordre du document.

  4. Le nœud de contexte des expressions calculées (intervenant sur l'élément bind) est le nœud en cours de traitement ;

  5. Pour les expressions de liaison de nœud simple, la dimension de contexte est celle de l'ensemble de nœuds, et la position de contexte est celle dans l'ordre du document du nœud en cours de traitement dans l'ensemble de nœuds ;

  6. Aucune liaison de variable n'est mise en place ;

  7. La bibliothèque des fonctions disponibles est définie ci-dessous, auxquelles s'ajoutent toutes les fonctions fournies par l'implémentation. Les fonctions d'extension nécessaires au fonctionnement du formulaire devraient se déclarer comme décrit dans 7.12 Les fonctions d'extension ;

  8. Toutes les déclarations d'espaces de nommage dans la portée de l'attribut qui définit l'expression sont appliquées à l'expression.

Exemple : Nœuds de contexte d'expressions de liaison
<group ref="niveau2/niveau3">
  <select1 ref="@attr" ... />
</group>

Dans cet exemple, l'élément group a l'expression de liaison niveau2/niveau3. Selon les règles précédentes, ce nœud d'élément le plus externe devrait avoir un nœud de contexte /niveau1, lequel est le nœud d'élément de niveau supérieur des données d'instance. La commande de formulaire select1 hérite alors du nœud de contexte de l'élément group parent. Les données d'instance correspondantes, représentées sous forme sérialisée XML, suivent :

Exemple : Données d'instance XML pour l'illustration
<niveau1>
  <niveau2>
    <niveau3 attr="xyz"/>
  </niveau2>
</niveau1>

7.5 Les expressions de liaison

Une expression de liaison correspond à une production PathExpr de XPath, et elle sert à lier une propriété d'élément de modèle à un ou plusieurs nœuds d'instance, ou à lier une commande de formulaire à des données d'instance, ou à spécifier le nœud, ou l'ensemble de nœuds, sur lequel une action s'exerce. Par défaut, toutes les expressions de liaison se rapportent à la première instance dans le modèle de contexte. On peut changer ce comportement à l'aide de la fonction instance().

7.5.1 Les dépendances dynamiques

Toutes les expressions XPath possibles ne font pas toutes une expression de liaison acceptable. En particulier, il existe des restrictions sur les expressions de liaison de modèle qui créent des dépendances dynamiques, lesquelles se définissent de la manière suivante :

Un prédicat XPath (entre crochets) correspond à un test booléen éventuellement implicite. Il existe une dépendance dynamique sur un prédicat, sauf si tous les termes du test sont fixes, où fixe signifie soit une constante, soit une valeur qui ne changera pas entre des opérations définies explicitement comme reconstruisant des dépendances de calcul.

Remarque :

Pour les besoins de la détermination des dépendances dynamiques, on considère les sous-expressions suivantes comme fixes : position(), last(), count() et property(). Et ceci, parce que la spécification impose une reconstruction de dépendance après tout événement susceptible de changer les valeurs renvoyées par ces fonctions.

Une autre dépendance dynamique est créée par l'utilisation de la fonction id(), à moins que le paramètre de la fonction et celui de l'attribut correspondant de type xsd:ID ne soient tous deux fixes. De même, la fonction instance() est dynamique, à moins que son paramètre ne soit fixe.

Les variables XPath dont la valeur change d'un recalcul à l'autre créeront également des dépendances dynamiques (bien que la recommandation XForms 1.0 définisse un contexte de variable vide pour toutes les expressions XPath).

Les auteurs qui définissent des fonctions d'extension sont invités à respecter ces règles.

7.5.2 Les expressions de liaison de modèle

Une expression de liaison de modèle est un type d'expression de liaison qui peut servir à déclarer des propriétés d'élément de modèle ; elle s'utilise dans les attributs de l'élément bind.

Les dépendances dynamiques dans les expressions de liaison de modèle nécessiteront généralement une reconstruction manuelle des dépendances.

7.5.3 Les expressions de liaison de l'interface d'utilisateur

Les appels de liaison peuvent servir à lier des commandes de formulaire aux données d'instance sous-jacentes comme décrit ici. Des noms d'attributs différents — ref et nodeset — distingue respectivement un nœud simple d'un ensemble de nœuds. Voir les sections 3.2.3 Les attributs de liaison de nœud simple et 3.2.4 Les attributs de liaison d'ensemble de nœuds.

Les dépendances dynamiques sont admises dans les expressions de liaison de l'interface d'utilisateur selon le profil de conformité.

7.5.4 Les liaisons de l'interface d'utilisateur dans d'autres vocabulaires XML

Le mécanisme de liaison de XForms permet aux autres vocabulaires XML de lier des commandes d'interface d'utilisateur à un modèle XForms au moyen de l'une des techniques présentées ici. Par exemple, on pourrait utiliser l'attribut de liaison XForms bind dans des commandes d'interface d'utilisateur XHTML 1.x comme montré ci-dessous. Voir les sections 3.2.3 Les attributs de liaison de nœud simple et 3.2.4 Les attributs de liaison d'ensemble de nœuds.

Exemple : Liaison XForms dans une commande d'interface d'utilisateur XHTML 1.x
<html:input type="text" name="..." xforms:bind="fn"/>

7.5.5 Exemples de liaisons

Soit le document suivant avec un seul modèle XForms :

<xforms:model id="commandes">
  <xforms:instance xmlns="">
    <bonCommande>
      <livrerChez>
        <prenom>John</prenom>
      </livrerChez>
    </bonCommande>
  </xforms:instance>
  <xforms:bind nodeset="/bonCommande/livrerChez/prenom" id="fn" />
</xforms:model>

Les exemples suivants montrent trois façons de lier la commande d'interface d'utilisateur xforms:input à l'élément d'instance prenom déclaré dans le modèle précédent.

Exemple : Liaison d'interface d'utilisateur avec l'attribut ref
<xforms:input ref="/bonCommande/livrerChez/prenom">...
Exemple : Liaison d'interface d'utilisateur avec l'attribut bind
<xforms:input bind="fn">...
Exemple : Indication explicite du modèle contenant l'instance
<xforms:input model="commandes" ref="/bonCommande/livrerChez/prenom">...

7.6 La bibliothèque de fonctions fondamentales de XForms

La librairie de fonctions fondamentales de XForms inclut celle de fonctions fondamentales de [XPath 1.0], y compris les opérations sur les ensembles de nœuds, les chaînes, les nombres et sur les booléens.

Les sections suivantes définissent d'autres fonctions nécessaires à utiliser dans XForms.

7.7 Les fonctions booléennes

7.7.1 La fonction boolean-from-string()

boolean boolean-from-string( chaîne )

La fonction boolean-from-string renvoie la valeur "true" si le paramètre demandé chaîne de type string est la chaîne "true", ou "1", ou elle renvoie la valeur "false" si le paramètre chaîne est la chaîne "false", ou "0". Elle se révèle utile lors de l'appel d'une valeur du type de donnée xsd:boolean du schéma dans une expression XPath. Si la chaîne paramètre ne correspond à aucune de celles mentionnées ci-dessus, selon une comparaison insensible à la casse, alors le traitement s'interrompt avec une exception (cf. 4.5.4 L'événement xforms-compute-exception) Si la chaîne paramètre correspond à l'une des précédentes, dans une comparaison insensible à la casse, la valeur de retour sera "false".

7.7.2 La fonction if()

string if( booléen, chaîne, chaîne )

La fonction if évalue le premier paramètre en tant que valeur booléenne de type boolean : s'il vaut "true", alors il renvoie le deuxième paramètre chaîne de type string, sinon il renvoie le troisième paramètre.

7.8 Les fonctions numériques

7.8.1 La fonction avg()

number avg( ensemble-de-nœuds )

La fonction avg renvoie la moyenne arithmétique du résultat de la conversion des valeurs de chaîne de chaque nœud de l'argument ensemble de nœuds en un nombre (type number). On obtient la somme en se servant de la fonction sum() ; on divise ensuite celle-ci, avec la fonction div(), par la valeur calculée au moyen de la fonction count(). Si son paramètre est un ensemble de nœuds vide ou si un nœud quelconque est évalué à "Nan", alors la fonction renvoie la valeur "NaN".

7.8.2 La fonction min()

number min( ensemble-de-nœuds )

La fonction min renvoie la valeur minimum du résultat de la conversion des valeurs de chaîne de chaque nœud de l'argument ensemble de nœuds en un nombre (type number). Le minimum se détermine avec l'opérateur <. Si son paramètre est un ensemble de nœuds vide, ou si l'un des nœuds était évalué à "NaN", alors la fonction renvoie la valeur "NaN".

7.8.3 La fonction max()

number max( ensemble-de-nœuds )

La fonction max renvoie la valeur maximum du résultat de la conversion des valeurs de chaîne de chaque nœud de l'argument ensemble de nœuds en un nombre (type number). Le maximum se détermine avec l'opérateur <. Si son paramètre est un ensemble de nœuds vide, ou si l'un des nœuds est évalué à "NaN", alors la fonction renvoie la valeur "NaN".

7.8.4 La fonction count-non-empty()

number count-non-empty( ensemble-de-nœuds )

La fonction count-non-empty renvoie le nombre de nœuds non vides dans l'argument ensemble de nœuds. Un nœud est considéré non vide s'il est converti en une chaîne dont la longueur est supérieure à zéro.

7.8.5 La fonction index()

number index( chaîne )

La fonction index admet comme argument une chaîne qui est la valeur de type IDREF d'un élément repeat, et elle renvoie la position courante commençant à 1 de l'index de répétition de l'élément repeat identifié (voir 9.3.1 L'élément repeat pour des précisions sur l'élément repeat et l'index de répétition qui lui est associé). Si l'argument fourni n'identifie aucun élément repeat, alors le traitement s'interrompt avec une exception (cf. 4.5.4 L'événement xforms-compute-exception) la fonction renvoie la valeur "NaN".

Exemple : Fonction index
<xforms:trigger>
  <xforms:label>Ajouter au panier d'achat</xforms:label>
  <xforms:insert ev:event="DOMActivate" position="after"
                 nodeset="articles/article" at="index('cartUI')"/>
</xforms:trigger>

7.9 Les fonctions de chaîne

7.9.1 La fonction property()

string property( chaîne )

La fonction property renvoie la propriété XForms nommée par le paramètre chaîne.

Les propriétés suivantes sont disponibles en lecture (mais pas en écriture).

version

La propriété version est définie comme étant la chaîne "1.0" pour XForms 1.0.

conformance-level

Les chaînes de la propriété conformance-level sont définies dans le chapitre 12 La conformité.

Exemple : Fonction property
<xforms:instance>
  ...
  <xforms:bind nodeset="message"
               calculate="concat( 'créé avec XForms ', property('version'))"/> ...
</xforms:instance>

7.10 Les fonctions de date et d'heure

Remarque :

Les types de données suivants du schéma XML ne disposent pas de fonctions de manipulation propres dans les expressions XForms : xsd:time, xsd:gYearMonth, xsd:gYear, xsd:gMonthDay, xsd:gDay, xsd:gMonth. On peut utiliser des fonctions d'extension (cf. 7.12 Les fonctions d'extension) pour effectuer les opérations nécessaires sur ces types de données.

7.10.1 La fonction now()

string now()

La fonction now renvoie la date et l'heure courantes du système sous forme d'une valeur de chaîne dans le format canonique xsd:dateTime du schéma XML. Si l'information de fuseau horaire est disponible, alors elle est comprise (normalisée au format UTC), sinon une valeur par défaut de l'implémentation sera utilisée.

Remarque :

Joindre le résultat d'un calcul now() à des données d'instance ne devrait pas aboutir à un flux de recalculs continus du modèle XForms.

7.10.2 La fonction days-from-date()

number days-from-date( chaîne )

Cette fonction renvoie un nombre de jours entier, selon les règles suivantes :

Si le paramètre chaîne représente une valeur lexicale légale de type xsd:date ou xsd:dateTime, alors la valeur renvoyée est égale à la différence en nombre de jours entre la date fournie (normalisée au temps universel coordonné UTC) et la valeur "1970-01-01". Les composants des heures, minutes et secondes sont ignorés après normalisation. Tout autre paramètre en entrée renverra la valeur "NaN".

Exemples :

days-from-date( "2002-01-01" ) renvoie "11688"
days-from-date( "1969-12-31" ) renvoie "-1"

7.10.3 La fonction seconds-from-dateTime()

number seconds-from-dateTime( chaîne )

Cette fonction renvoie un nombre éventuellement fractionnel de secondes, selon les règles suivantes :

Si le paramètre chaîne représente une valeur lexicale légale de type xsd:dateTime, alors la valeur renvoyée est égale à la différence en nombre de secondes entre la valeur de type dateTime fournie (normalisée au temps universel coordonné UTC) et la valeur "1970-01-01T00:00:00Z". Si aucun fuseau horaire n'est indiqué, alors la valeur par défaut fournie par la mise en œuvre sera utilisée il s'agit alors du temps universel coordonné UTC. Tout autre paramètre de chaîne en entrée renverra la valeur "NaN".

7.10.4 La fonction seconds()

number seconds( chaîne )

Cette fonction renvoie un nombre éventuellement fractionnel de secondes, selon les règles suivantes :

Si le paramètre chaîne représente une valeur lexicale légale de type xsd:duration, alors la valeur renvoyée est égale au nombre fourni dans le composant des secondes plus 60 fois le nombre indiqué dans le composant des minutes, plus 60 * 60 fois le nombre indiqué dans le composant des heures, plus 60 * 60 * 24 fois le nombre indiqué dans le composant des jours. Le signe du résultat correspondra à celui de la durée. Si aucun fuseau horaire n'est indiqué, alors la valeur par défaut fournie par la mise en œuvre sera utilisée. Les composants des années et des mois, s'ils sont présents, sont ignorés. Tout autre paramètre en entrée renverra la valeur "NaN".

Exemples :

seconds( "P1Y2M" ) renvoie "0"
seconds( "P3DT10H30M1.5S" ) renvoie "297001.5"
seconds( "3" ) renvoie "NaN"

Remarque :

Bien que cette fonction soit définie à partir d'un type lexical xsd:duration, elle n'est prévue que pour une utilisation avec des types de données dérivés de xsd:duration, notamment le type de donnée xforms:dayTimeDuration.

7.10.5 La fonction months()

number months( chaîne )

Cette fonction renvoie un nombre de mois entier, selon les règles suivantes :

Si le paramètre chaîne représente une valeur lexicale légale de type xsd:duration, alors la valeur renvoyée est égale au nombre indiqué dans le composant des mois plus 12 fois le nombre indiqué dans le composant des années. Le signe du résultat correspondra à celui de la durée. Les composants des jours, heures, minutes et secondes, si présents, seront ignorés. Tout autre paramètre en entrée renverra une valeur de "NaN".

Exemples :

months( "P1Y2M" ) renvoie "14"
months( "-P19M" ) renvoie "-19"

Remarque :

Bien que cette fonction soit définie à partir d'un type lexical xsd:duration, elle n'est prévue que pour une utilisation avec des types de données dérivés de xsd:duration, notamment le type de donnée xforms:yearMonthDuration.

7.11 Les fonctions d'ensemble de nœuds

7.11.1 La fonction instance()

node-set instance( chaîne )

Un modèle XForms peut contenir plusieurs instances : cette fonction permet d'accéder aux données d'instance, dans le même modèle XForms mais hors des données d'instance contenant le nœud de contexte.

L'argument est converti en une chaîne comme par un appel à la fonction string. Cette chaîne est traitée comme une valeur de type IDREF, qui est comparée aux éléments instance dans le document conteneur. Si une correspondance est trouvée et que les données d'instance filtrées sont associées au même modèle XForms en tant que nœud de contexte courant, alors cette fonction renvoie un ensemble de nœuds contenant uniquement le nœud d'élément racine (aussi appelé nœud d'élément document) des données d'instance appelées. Dans tous les autres cas, il sera renvoyé un ensemble de nœuds vide.

Exemple :

Pour les données d'instance correspondant à ce fragment XML :

<xforms:instance xmlns="" id="boncommande">
  <bonCommande>
    <livrerChez>
      <prenom>John</prenom>
    </livrerChez>
  </bonCommande>
</xforms:instance>

L'expression suivante sélectionne le nœud prenom. Remarquez que la fonction instance renvoie un nœud d'élément, en remplaçant effectivement le pas d'emplacement du chemin le plus à gauche :

ref="instance('boncommande')/livrerChez/prenom"

7.12 Les fonctions d'extension

Les documents XForms peuvent utiliser d'autres fonctions d'extension XPath, en plus de celles décrites ici. Un certain nombre d'extensions communautaires utiles sont définies à [EXSLT]. Les noms de ces functions d'extension doivent être déclarées dans l'attribut functions de l'élément model. Ces déclarations servent au processeur XForms à vérifier les fonctions d'extension disponibles. Le processeur XForms effectue cette vérification au chargement du document ; le processeur interrompt le traitement en signalant une exception (cf. 4.5.4 L'événement xforms-compute-exception) si le document XForms déclare une fonction d'extension pour laquelle il ne dispose pas d'une implémentation.

Remarque :

La déclaration explicite des fonctions d'extension permet aux processeurs XForms de détecter l'utilisation de fonctions d'extension non implémentées dès le chargement du document plutôt que de risquer une erreur fatale pendant l'interaction de l'utilisateur. La non-déclaration des fonctions d'extension par les auteurs amènera éventuellement le processeur XForms à interrompre le traitement pendant l'interaction de l'utilisateur avec une erreur fatale.