Google Chercher dans diml.org
[ english ]

Table des matières
1. Motivation
2. Définitions
3. Extensions de fichiers et types MIME type
4. La syntaxe DIML
4.1 instructions DIML
4.1.1 Instructions
4.1.2 Commentaires DIML
4.2 Balises d'injection de données
4.2.1 Accès aux variables
4.2.1.1 Variables textuelles
4.2.1.2 Variables scalaires
4.2.1.3 Conversions implicites imbriquées
4.2.2 Vecteurs
4.2.2.1 Appels vectoriels
4.2.2.2 L'opérateur vectoriel []
4.2.2.3 Accès relatif
4.2.2.4 Valeur vectorielle et valeur scalaire d'une variable
4.2.2.5 Accès aux indices courants de vecteurs
4.2.2.6 Appels vectoriels dans le corps principal de document
4.2.2.7 Vecteurs multidimensionnels, matrices
4.2.2.8 Matrices de listes
4.2.3 Formatage des chaînes substituées
4.2.3.1 Quand doivent être écrits les attributs de format
4.2.3.2 L'attribut MAXLENGTH
4.2.3.3 L'attribut MINLENGTH
4.2.3.4 L'attribut DEFAULT
4.2.3.5 L'attribut NULL
4.2.3.6 L'attribut FORMAT
4.2.4 Noms de variables prédéfinis
4.2.4.1 La variable %NULL%
4.2.4.2 La variable %ERROR%
4.2.4.3 Les variables %CGI::...%
4.2.4.4 Les variables %ENV::...% d'environnement
4.2.4.4 Les variables %FORM::...% de formulaires
4.2.5 Définition de variables à partir du DIML
4.2.5.1 Pourquoi ?
4.2.5.2 Définir des variables par définition de templates, l'attribut INLINE
4.2.5.3 L'instruction SET
4.2.5.4 L'instruction EVAL
4.3 Balises de structure
4.3.1 L'élément TEMPLATE
4.3.1.1 Définition de templates
4.3.1.2 Attributs
4.3.1.3 Contenu de l'élément TEMPLATE
4.3.2 Appels de templates
4.3.2.1 Appels simples
4.3.2.2 Appels vectoriels
4.3.2.3 Outrepasser la limite du nombre maximum d'itérations
4.3.2.4 Règles pour la réutilisation de templates ou de variables
4.3.2.5 Appels vectoriels imbriqués
4.3.2.6 Simplification de l'accès aux templates locaux
4.3.3 Import de templates externes
4.3.3.1 Distinction entre l'appel et l'import
4.3.3.2 L'instruction IMPORT
4.3.4 Instructions d'arrêt
4.3.4.1 L'instruction END
4.3.4.2 L'instruction STOP
4.3.5 Instruction d'incrémentation
4.3.5.1 L'instruction BLIND
4.3.5.2 L'instruction NEXT
4.3.5.3 L'instruction STOP
4.3.5.4 L'instruction REWIND
4.4 Expressions
4.4.1 Structures conditionnelles
4.4.1.1 La structure IF...ELSIF...ELSE...ENDIF
4.4.1.2 La structure conditionnelle monoligne
4.4.1.3 La structure conditionnelle multiligne
4.4.1.4 Opérateurs et variables dans les conditions
4.4.1.5 Evolution future : La structure SWITCH...CASE
5. Structure des documents DIML
5.1 Section principale
5.2 Templates
5.2.1 Appels vectoriels de variables dans une définition de template
6. Alimentation de données
6.1 Appel par un script d'alimentation
6.2 Appel d'une fonction d'alimentation
6.1.1 L'instruction INVOKE
6.1.2 Fonction d'alimentation par défaut
A. Appendices
Appendice 1 : Le modèle de tableaux multidimentionnel du DIML
Appendice 2 : Références
Appendice 3 : Remerciements
 Dernières infos
 Une application du composant  WCT_NEWS  
>> Haut de la page

Data Injection Markup Language

Specification de l'extension ESSI

Auteur: V.G. FREMAUX
E.I.S.T.I. / Cergy, France
Laboratoire de Recherche Appliquée
Nouvelles Technologies de l'Information et de la Communication

Version: 1.2 / Juin 2002

0. Objet de ce document

Ce projet de spécification est le résultat d'un travail effectué dans le cadre des recherches appliquées de l'Ecole Internationale des Sciences du Traitement de l'Information de Cergy (France), en vue de la mise en place du Laboratoire des Nouvelles Technologies de l'Information et la Communication. Nous ne savons pas, au moment de cette traduction, l'issue possible pour cette spécification, son usage futur, ni même si elle sera publiée officiellement un jour.

Cependant, à supposer qu'elle le soit dans le futur, nous nous sommes engagé à la rédiger dans le cadre d'une telle éventualité, et à joindre le maximum de documentation en support.

1. Motivation

La présente spécification propose une approche assez nouvelle dans le domaine des langages utilisés pour la conception de documents Web. Nous pourrons citer les travaux d'un certain nombre de chercheurs et ingénieurs qui ont, comme nous, ressenti le même besoin en fin de cette étude.

La plupart des langages de script actuels tendent à imbriquer intimement les instructions de présentation, et le code régissant la logique de construction de la page Web. Par exemple, des langages tels que php ou le VBScript utilisé pour les pages ASP&tm; conduit naturellement à une écriture très fortement imbriquée de code HTML et d'instructions de script.

Il en résulte une insatisfation latente, tant chez les designers de pages que chez les auteurs de scripts. Dans un monde idéal, une parfaite et productive coopération entre les programmeurs et les concepteurs devrait pouvoir être imaginable, chacun sachant où se situerait la limite qui le sépare de l'autre.

Dans ce monde idéal, nous pourrions prévoir que les programmeurs soient plus particulièrement intéressés de savoir comment les systèmes qu'ils manipulent sont implémentés et comment leur fonctionnement peut être optimisé ou leurs potentialités accrues.

D'un autre côté, les concepteurs pourraient apprécier que tout ce qui ait trait au dynamisme et aux procédures de traitement de données soit totalement et définitivement résolu, quelque soit la complexité du processus. L'essentiel du travail du concepteur pourrait être alors... de concevoir les interfaces.

La tendance des langages de scripts seraient malheureusement plutôt à vouloir mélanger de plus en plus la présentation et la logique, plutôt que de les isoler.

De cette confusion il découle que des mécanismes apparemment standardisables doivent être redéveloppés en permanence, simplement parce que de nombreux points concernant la présentation ont changé entre deux projets similaires, ou à l'inverse parce que les fonctionnalités ont quelque peu divergé.

La présente proposition, sous forme d'une extension côté serveur du HTML, représente une solution possible pour améliorer l'interface entre l'informatique et la "communication". L'extension présentée sépare définitivemet la logique impliquée dans une fonctionnalité client-serveur des nécessités de codage de la présentation et la mise en page.

Des investigations complémentaires sur les syntaxes ODBC Microsoft&tm; utilisées sur la plate-forme IIS ont confirmé les premières hypothèses de la syntaxe du DIML. Pour des raisons de simplicité et de cohérence culturelles, nous avons décidé de nous inspirer de la syntaxe des fichiers XTH MicrosoftTM, tout en développant spécifiquement les primitives qui nous semblaient nécessaires.

De plus, la présente spécification, en introduisant un principe de réutilisabilité et de factorisation du fond, se situe à mi-chemin des concepts du HTML d'une part, et du XML d'autre part. La conception de documents basés sur XML (et les standards connexes XSL et DOM) est une tâche qui devient très rapidement gigantesque, voire quasiment inextricable pour des documents complexes, et qui demande une longue et exhaustive étude de la structure documentaire globale prise dans son ensemble. Les techniques introduites par le DIML sont un premier pas conduisant à la factorisation d'information qui préfigure la puissance conceptuelle de XML, mais avec un degré de complexité bien moindre.

2. Définitions

L'extension ESSI
L'extension ESSI (Enhanced Server-Side Includes) étend les possibilités des techniques SSI, en fournissant un moyen simple de marquer un document HTML pour y injecter des données textuelles issues d'un script. Le deuxième apport de cette extension est le mécanisme de définition puis de réutilisation de fragments de HTML.
Templates
La technologie ESSI permet à son utilisateur de définir des fragments HTML ("templates") utilisés comme composants structurels d'un document. Alors que les feuilles de styles permettent une factorisation des attributs de style, les "templates" sont un moyen puissant d'organisation du fond dansun but de réutilisabilité.
La définition ESSI s'appuie sur la technique consistant à éclater un document HTML en un grand nombre d'entités "informationnelles" autonomes qui peuvent être ensuite "montées" dans une mise en page.
Par example, une pratique courante de design Web pour simuler des cadres pour des applications large bande est d'utiliser un motif de fond bi ou tricolore, associé à une mise en forme tabulée adéquate. Cette technique conduit à l'écriture d'une seule page HTML dans laquelle l'information de la "page" proprement dite suit le code du cadre simulé. Pour le concepteur cependant, il s'agit toujours de deux entités sémantiques totalement différentes, bien que le code soit rassemblé en un seul et unique fichier.
La spécification des "templates" ESSI permettra de distinguer explicitement les deux définitions, de stocker ces définitions dans des fichiers différents, et les recomposer comme l'aurait fait une instruction <!--#include ...--> SSI classique. Par rapport au SSI, les apports de la technologie ESSI sont :
  • la possibilité de stocker les fragments HTML dans le même document que celui qui les appelle,
  • dans le même ordre d'idées, la possibilité d'organiser les fragments totalement indépendamment de la répartition en fichiers,
  • une écriture extrêmement simple des inclusions itératives effectuées par exemple dans le cas d'extraction d'enregistrements de base de données, ou tout autre construction itérative.
  • une possibilité d'isoler totalement les écritures fonctionnelles d'un contrôle des écritures de forme.
Ces avantages sont les premiers à nous venir à l'esprit. De nombreuses autres fonctionnalités risquent d'être incluses au fur et à mesure du développement des premiers prototypes.
Marquage de l'injection de données
De ce fait, l'extension ESSI définit une syntaxe pour marquer les points d'injection de données à partir d'un script d'alimentation. Cette syntaxe a été fortement motivée par l'analyse d'une construction typique de traitement CGI que nous pouvons résumer par :
  1. le décodage de la chaîne de requête CGI
  2. le calcul, l'extraction, la sélection des données à afficher, l'ouverture de fichiers, de bases de données, l'envoi de résultats par messagerie, fax...
  3. l'impression d'une réponse au requérant
Ainsi, dès que toutes les informations nécessaires à la construction de la réponse sont constituées, on peut supposer qu'il ne reste qu'à lancer une commande d'impression sur le flux de sortie. L'écriture de cette séquence d'impression dans le source du script ne permet qu'exceptionnellement une séparation effective de la logique et des données de présentation.
La syntaxe définie ici permet de standardiser la procédure d'appel de variables dans un modèle ESSI (ou encore, de fragments HTML dans un masque d'injection ESSI).
L'idée fondamentale développée ici est qu'une réponse client puisse être systématiquement la synthèse d'un masque et d'un ensemble de données, lesquelles seraient injectées à leur place respectives dans le but de produire un code final HTML parfaitement conforme, pour enfin envoyer ce HTML résultant au client. Notre procédé d'injection vient démontrer ce concept.
API des processeurs ESSI
Enfin, l'extension ESSI définit une API particulière de l'implémentation des préprocesseurs ESSI. Cette API permet la prédéfinition de certaines procédures de vérification et oriente la nature de certains comportements par défaut des préprocesseurs chargés de la résolution des "templates", et plus particulièrement dans le cas des structures itératives, dans un soucis permanent de robustesse. Cette API sera décrite dans un document annexe.
Préprocesseur ESSI
Pour répondre aux exigences du système, les sources ESSI (contenant une combinaison de balises HTML et des instructions DIML) devront être traités avant d'être acheminés vers le client. Le préprocesseur ESSI effectue ce traitement.
Une première version du préprocesseur est disponible en Perl et pour des applications php. L'intégration de cette technique sous ASP ou dans un contexte de Servlets sera étudiée par la suite.
La fonction préprocesseur ESSI interprète les instructions DIML, génère un pseudo fichier HTML contenant des marqueurs d'injection de variables, remplace les marqueurs par la valeur finale de la variable, puis renvoie le document HTML final à la fonction appelante.
Le préprocésseur existera aussi en version autonome.

3. Extensions de fichiers et types MIME type

L'extension ESSI et le DIML produisent des fichiers "HTML étendu" dans lesquels les "templates" sont définis. Ces fichiers devront être traités par un algorithme serveur avant d'être envoyés au client.

Le code HTML des pages contenant des éventuels "templates", ainsi que des instructions d'injection seront écrits dans des fichiers d'extension .dim ou .diml. Une définition d'un type MIME particulier devrait être déposée dans un futur proche.

4. La syntaxe DIML

4.1 Instructions DIML

4.1.1 Instructions

Pour que le préprocesseur ESSI puisse identier les balises DIML à interpréter, chaque instruction DIML sera enchassée entre un marqueur de début et un marqueur de fin. La paire de marqueurs choisie est <% ... %>.

Par défaut, on supposera que la conversion finale d'une instruction DIML, appelée aussi contrepartie de l'instruction est toujours une conversion en une expression de type chaîne de caractères. Lorsque l'instruction est exécutée, une chaîne de caractère correspondant à la conversion la plus plausible du résultat de l'expression devra être renvoyée. Si l'expression à exécuter ne doit pas renvoyer de valeur, cette conversion n'a pas lieu d'être. La chaîne vide sera injectée dans ce cas.

Les instructions DIML sont regroupées en deux catégories :

Les balises structurelles
Les balises structurelles définissent les fragments de DIML (templates), ainsi que certaines constructions logiques d'assemblage de la page.
Les instructions d'injections de données
Les balises d'injection de données interviennent lorsqu'une variable ou un fragment doit être appelé, en réglant quelques paramètres destinés à contrôler le format de la chaîne produite.

4.1.1 Commentaires DIML

Compatibilité : Version 1.2

Bien que le HTML donne déjà un mécanisme de marquage de commentaires tout à fait utilisable, le DIML permet également d'insérer des commentaires dans le code de la page. Contrairement à ceux du HTMl qui resteront dans la page finale, les commentaires du DIML sont éliminés lors de la production de la page dans le serveur. Il sont principalement destinés aux développeurs des pages.

L'instruction COMMENT permet de placer un bloc de commentaires dans le document :

<%comment une séquence de commentaires %>

Pour des raisons pratiques, cette syntaxe a été surchargée par une syntaxe classique :

<%! une séquence de commentaires %>

4.2 Balises d'injection de données

4.2.1 Accès aux variables

4.2.1.1 Variables textuelles

Dans la majorité des cas, les noms symboliques de variables seront utilisés pour appeler une valeur qui doit être injectée en tant qu'élément textuel dans la trame HTML finale. Une variable ESSI est un identificateur ASCII étendu inséré entre deux caractères '%'.

variable ::= %identificateur%

et répond à l'expression régulière suivante :

identificateur ::= [^%*?.+"><\^\\\$]*

L'expression régulière précédente interdit donc l'usage du marqueur de fin de variable '%', des métacaractères '*', '?', '.', '+', '^' et '$', ainsi que des délimiteurs et caractères spéciaux '"', '>', '<', et '\'.

example :

%A_VARIABLE%

Leur utilisation suppose que l'identificateur constitué soit une clef valide de la structure d'entrée du préprocesseur ESSI. (voir le document essi_api.htm pour plus de détails).

Dans le cas courant, la variable est simplement substituée à la balise dans le flux HTML. Dans ce cas, la variable sera automatiquement convertie dans sa représentation textuelle telle que le demande la règle générale de balisage ESSI. Par exemple, considérons une ligne de table de base de données contenant des données de catalogue produit telles qu'un nom de produit, un code de référence, une quantité disponible et un prix unitaire. Un fragment DIML pour injecter ces données pourrait être écrit ainsi :

<TR>
<TD>
<FONT COLOR="#800000"><%%ITEM_NAME%%></FONT>
</TD>
<TD WIDTH=200>
<%%ITEM_CODE%%>
</TD>
<TD ALIGN=right>
<FONT SIZE=+1><STRONG><%%UNITY_PRICE%%></STRONG></FONT>
</TD>
</TR>

Pour des raisons de lisibilités dans de grands fichiers DIML, il sera possible d'insérer des espaces entre les marqueurs de balisage DIML et l'appel de variable lui-même :

<%%A_VARIABLE%%> 

est alors équivalent à

<% %A_VARIABLE% %>

Par contre, les syntaxes

< %%A_VARIABLE%% >
< % %A_VARIABLE% % >

sont illégales et doivent être sanctionnées par une erreur du préprocesseur, les syntaxes

<%% A_VARIABLE %%>
<% % A_VARIABLE% % >

sont légales mais peuvent conduire à une variable ' UNE_VARIABLE ' pour certains preprocesseurs.

4.2.1.2 Variables scalaires

Il peut arriver que l'expression primaire d'une variable soit utilisée dans une instruction DIML, en particulier dans une condition d'instruction conditionnelle.

Dans de telles constructions, l'identificateur (sans marqueurs de variable peut être utilisé pour accéder à la valeur réelle de la variable. Si cette donnée est originellement une chaîne (respectivement un entier, un flottant, un booléen...), alors

%variable%

sera l'interprétation chaîne équivalente de la variable (la conversion dépend du type de départ). Dans l'expression suivante :

<%if (test_value) ... fin de l'instruction DIML %>

le préprocesseur devrait considérer la valeur réelle de la variable identifiée par test_value pour le test.

La plupart des langages de script ont défini une syntaxe pour "imprimer" des variables internes dans le flux HTML de sortie. Voici quelques équivalences typiques de syntaxes correspondant à l'injection d'une variable :

ESSI

<%%A_VARIABLE%%>

Php

<? echo "$VARIABLE"; ?>

ASP

<%=VARIABLE %>

Microsoft XTH

<%VARIABLE%>

CGI Perl

print STDOUT "$VARIABLE";

CGI C

printf("%chaîne_format", VARIABLE);

4.2.1.3 Conversions implicites imbriquées

La chaîne de caractères obtenue par substitution d'une variable pourra elle-même contenir d'autres variables à substituer. L'exemple ci-dessous montre une telle situation, après qu'un appel à un "template" ait été exécuté :

<% début du template... <%%VARIABLE%%> .. fin du template %>

Dans une telle situation, l'expression extérieure (le template) serait remplacé par son contenu, comme il se doit. L'expression résultant serait alors interprétée de nouveau pour remplacer tout appel de variable interne.

La recherche d'instructions se poursuit jusqu'à ce que plus aucun appel de substitution ne demeure.

DANS TOUS LES CAS, LA RECURSION D'ANALYSE DES INSTRUCTIONS DIML SE POURSUIT TANT QU'APPARAIT UNE DES SYNTAXES CONNUES PAR LE PREPROCESSEUR, QUE CE SOIT EXPLICITEMENT OU IMPLICITEMENT A L'EXECUTION. TOUT APPEL IMBRIQUE DEVRA CEPENDANT UTILISER LA SYNTAXE D'ECHAPPEMENT DU SGML.

De ce fait, l'instruction :

<% Instruction DIML .. <% autre instruction DIML %> .. fin d'instruction %>

est illegale. Un tel appel imbriqué devra être écrit :

<% Instruction DIML .. &lt;% autre instruction DIML %&gt; .. fin d'instruction %>

4.2.2 Vecteurs

4.2.2.1 Appels vectoriels

L'un des objectifs principaux de la définition du DIML est de pouvoir totalement dissocier la présentation (l'enrobage) des parties logiques du traitement. Cela reste difficilement possible lorsque le document résulte d'une contruction itérative, par exemple, lorsque fondé sur l'extraction d'une base de données.

En général, le code de requête, de lecture, de traitement et de rendu de champs de données d'un enregistrement nécessite que ces deux aspects du codage soient souvent enchevêtrés.

La technique d'appel vectoriel d'une variable DIML constitue en cela une solution pratique.

4.2.2.2 L'opérateur vectoriel []

Lorsqu'une variable est appelée suivie de l'opérateur [] (exemple : %VARIABLE[]%) cette variable est supposée être une valeur dans un vecteur de résultats.

Les valeurs dans la variable tableau sont évaluées dans l'ordre d'index de la constitution de ce tableau, successivement. L'incrémentation des indices d'accès aux vecteurs est liée à l'appel des "templates". De ce fait, plusieurs appels successifs au même vecteur dans un même "template" produiront toujours la même valeur. L'exemple :

<TEMPLATE id="testTemplate">
<TR><TD><%%TABLEAU[]%%></TD><TD><%%TABLEAU[]%%></TD>><TD><%%TABLEAU[]%%>
</TD></TR>
</TEMPLATE>

construit une ligne de table HTML contenant trois fois la même valeur lue dans le vecteur %TABLEAU[]% à la valeur d'index courant.

4.2.2.3 Accès relatif

Il peut être intéressant de pouvoir, à un instant donné, avoir accès à d'autres valeurs que celle pointé par l'index courant du vecteur. La syntaxe DIML devra pouvoir permettre d'accêder ainsi à une position relative différente de celle pointée par l'index courant.

Cette position relative pourra être symbolisée par un décalage avant ou arrière dans la table, par exemple :

%TABLEAU[-1]% 

permettra d'obtenir la valeur précédent la valeur courante dans le vecteur TABLEAU. %TABLEAU[+2]% permetrait de rapatrier une valeur avec deux positions d'avance par rapport à la position courante dans le vecteur TABLEAU. Tout pointage "hors indice" se traduira par une variable résultante substituée %NULL%.

4.2.2.4 Valeur vectorielle et valeur scalaire d'une variable

Un nom de variable pourrait être utilisé simultanément pour désigner un vecteur (dans sa forme vectorielle), et une variable scalaire. Si cela arrive, les deux variables (scalaire et vecteur) sont totalement indépendantes et ne doivent être confondues.

%variable%

ajoute une valeur supplémentaire indépendante à la sémantique

%variable[]%
4.2.2.5 Accès aux indices courants de vecteurs

Pour chaque forme vectorielle utilisée dans un document on stockera une variable d'indice (de portée limitée au document lui-même) pilotant l'exploration du vecteur au fur et à mesure de l'appel de "templates". Les implémentations restent libre de déterminer la forme de cette variable d'indice, bien que la forme suivante soit conseillée par souci de cohérence :

%TABLEAU[]% indicé par %TABLEAU§I%

Notez qu'il faudra stocker un indice par dimension d'exploration de la matrice.

4.2.2.6 Appels vectoriels dans le corps principal de document

Par construction, l'usage de vecteurs était essentiellement prévu pour une utilisation via des "templates" itératifs. Que devrait-il se passer en cas d'appel vectoriel dans le corps principal d'un document DIML ?

La réponse la plus simple à apporter est d'accéder à la valeur vectorielle à l'indice courant, dont la valeur aura été déterminée par l'itération automatique précédente. De part la règle primordiale qui associe l'itération des indices à l'appel de "templates", les appels vectoriels à partir du corps principal de document n'activeront pas le mécanisme d'incrémentation d'indice.

4.2.2.7 Vecteurs multidimensionnels, matrices

Dans le cas d'imbrication d'appels de "templates", il peut être envisagé des appels à une variable dans le but de parcourir une matrice multidimensionnelle. Par exemple, lorsqu'à l'aide d'une simple variable %CELLULE% l'on parcourt une table de paramètres à deux dimensions. Dans ce cas, il sera convenable d'utiliser une forme matricielle de la variable, telle que :

%CELLULE[][]%

Grâce à cette forme, on pourra produire une écriture de parcours de tableau à l'aide du code suivant :

<TEMPLATE ID=une_cellule>
<TD><FONT COLOR="#000080><%%CELL[][]%%></FONT></TD>
</TEMPLATE>

intégré dans la définition d'une ligne :

<TEMPLATE ID=une_ligne>
<TR>
<%template file=#labels_lignes>
<%template file=#une_cellule iterate=3>
</TR>
</TEMPLATE>

dans laquelle "labels_lignes" pourrait être un "template" définissant les libellés de ligne :

<TEMPLATE ID=#labels_lignes>
<TD><%%LINE_LABEL[]%%></TD>
</TEMPLATE>

Préciser ici comment l'itération se produit pourra paraître quelque peu compliqué, et est influencé fortement par l'implémentation, mais est certainement nécessaire pour bien faire sentir les possibilités d'une des syntaxes les plus puissantes de la spécification du DIML.

Dans le cas général, lorsqu'une variable vectorielle ou matricielle est évaluée, le processeur détermine les valeurs d'indice par lecture des variables typiques d'indiçage associées. Aucun indice n'évolue pendant cette opération. C'est au retour de substitution de la totalité du "template" que les opérations sur les indices s'effectuent. L'indice de plus faible poids sera incrémenté par la conclusion du "template" immédiatement supérieur. Le traitement de l'indice suivant est effectué dans la conclusion du "template" au dessus, avec pour effet de remettre à 0 tous les indices de niveau inférieur. L'exploration d'une double inclusion de "template" produira de ce fait un parcours tabulaire d'une matrice ligne/colonne.

4.2.2.8 Matrices de listes

Compatibilité : 1.2

Une forme communément employée dans les documents est le tableau de listes ou la matrice de listes. Cette forme correspond par exemple à l'extraction de listes de propriétés dans un ensemble de définitions. L'ensemble peut lui-même être défini comme un vecteur monodimensionnel de valeurs, ou comme une matrice. L'accès à une matrice de liste combine la forme d'accès vectorielle à la forme itérative, produisant la sortie de tous les résultats disponibles.

%LISTES[][][*]%

La version 1.2 du DIML prend en charge le vecteur de liste de la façon suivante. La syntaxe d'appel est celle du tableau ou de la matrice à l'indice courant, excepté pour la dernière dimension qui produit une itération de l'indice courant au moment de l'appel à l'indice de comptage défini par le constructeur du tableau pour la liste concernée. Ceci suppose la fourniture des indices de comptage pour chacune des listes constituant une cellule de la sous-matrice de dimension n-1. Il s'agit d'une extension exacte du principe d'appel introduit à partir du 4.3.2.2 Appels vectoriels.

Le principe de la liste monodimensionnelle est repris pour les indices de comptage. Par extension de la forme :

LISTE_SIMPLE§C

de la liste monodimensionnelle, la définition de vecteurs de listes ou de matrices de listes nécessite la fourniture de la matrice des indices de comptage associée :

VECTEUR_DE_LISTE§C[]
MATRICE_DE_LISTE§C[][]

dont la dimension est toujours inférieur d'une unité de celle de la structure de listes. On notera en effet que la valeur de cellule de cette table des indices est la valeur de comptage de la dernière dimension de la matrice de listes.

La version 1.2 du DIML ne définit pas la notion de listes de listes (les syntaxes %VAR[]...[][*]...[*]% ne sont pas légales).

4.2.3 Formatage des chaînes substituées

La syntaxe DIML est essentiellement destinée à injecter des données textuelles brutes à partir de bases de données ou d'extraction de textes. De ce fait, la definition du DIML doit prévoir de pouvoir déléguer le plus d'aspects présentationnels au HTML englobant. Il est malheureusement possible (voire courant) que des valeurs particulières viennent perturber la mise en page de documents, simplement parce que d'une longueur non prévue, ou sous une forme non traitée. Ces perturbations sont notables en particulier dans toutes les applications utilisant des algorithmes automatiques de mise en page, et en particulier la mise en page sur le Web.

Par défaut, la substitution effectuée ne subit pas de formatage (c'est-à-dire que la chaîne de caractère obtenue après substitution n'est pas limitée en taille, et sera injectée dans sa totalité).

La syntaxe DIML permet un contrôle à partir de la couche présentation de certains paramètres de format de la chaîne résultat. Il en résultera la définition d'attributs additionnels, venant compléter la syntaxe d'injection. Certains de ces paramètres seront également utilisables dans le cas de "templates".

4.2.3.1 Quand doivent être écrits les attributs de format

Les attributs de format sont des paramètres ayant une influence directe sur la conversion de la variable en chaîne de caractères finale. De ce fait, toute implémentation DIML devra prévoir leur présence, partout ou nécessaire.

Le premier usage des paramètres de format intervient dans le cas d'une substitution simple :

%Une_Variable MAXLENGTH=10 FORMAT=###.##%

Cependant, des modificateurs de format pourront aussi être utilisés pour calibrer l'expression finale (dans un tel cas, applicables à la dernière conversion caractères de l'expression toute entière). Ce qui suit est de ce fait acceptable :

<%if (test) %variable FORMAT=#*.###E% else %alternate FORMAT=0*H% MAXLENGTH=6 %>

L'attribut MAXLENGTH serait alors distribué dans les deux alternatives de l'instruction <%if ... %>.

4.2.3.2 L'attribut MAXLENGTH

Usage :
Appels de templates, Appels de variables, instruction DIML

L'attribut MAXLENGTH définit le nombre de caractères maximum que peut contenir la chaîne produite par l'expression à laquelle il est appliqué. L'argument de l'attribut MAXLENGTH est un entier exprimant un nombre de caractères. Si le résultat de l'expression concernée est une chaîne d'une longueur supérieure à MAXLENGTH, alors la chaîne résultat sera tronquée autant que nécessaire.

Cet attribut peut être utilisé par un designer pour "protéger" une mise en forme contre des données inconsistantes. Le résultat du calage ne peut toutefois pas être connu à l'avance avec grande précision, étant donnée les différences de largeurs de caractères dans la plupart des polices.

4.2.3.3 L'attribut MINLENGTH

Usage :
Applels de templates, appels de variables, instruction DIML

L'attribut MINLENGTH définit le nombre de caractères minimum que doit occuper la chaîne produite par l'expression à laquelle il est appliqué. L'argument de l'attribut MINLENGTH est un entier représentant le nombre de caractères minimal de la chaîne.

Le premier comportement de ce paramètre est de forcer l'ajout d'espaces non sécables à la chaîne produite, si celle-ci ne contient pas assez de caractères. La chaîne résultante aura donc au minimum MINLENGTH, qui pourront être interprétés sur une base de pixels en cas d'une police à largeur fixe.

4.2.3.4 L'attribut DEFAULT

Usage :
Appels de variable, Instruction DIML

L'attribut DEFAULT permet à l'utilisateur de préciser quelle est la chaîne qui sera inscrite si l'expression aboutit à la chaîne vide. La chaîne DEFAULT par défaut est la chaîne vide ("").

4.2.3.5 L'attribut NULL

Usage :
Appels de variables, Instrucion DIML

L'attribut NULL permet à l'utilisateur de définir une chaîne par défaut si la variable ne renvoie pas de chaîne exploitable (une variable prédéfinie %NULL%, ou dans le cas d'une impossibilité de calcul).

4.2.3.6 L'attribut FORMAT

Usage :
Appels de variables

L'attribut FORMAT permet aux designers de garder un certain controle sur le format d'affiche des variables numériques. L'action finale du processeur ESSI est toujours de proposer une représentation chaîne de caractères de toute variable. Cet attribut ajoute quelques possibilités de contrôle dans la façon dont cette représentation est construite.

La valeur de cet attribut est un masque qui indique comment la variable numérique doit être interprétée. Le masque devra apparaître entre guillemets, étant donné la forte probabilité d'espaces litéraux.

Les symboles usuels de présentation dans le masque sont :

# - une position de nombre, si significatif.

0 - force l'affichage d'un 0 à cette position
s'il n'était pas significatif, ou alors le nombre.

. - la position de la décimale (décimale anglo-saxone '.')

, - la position de la décimale (décimale latine ',')

e - A la fin du masque uniquement, impose une notation scientifique
à un chiffre de mantisse significatif, et l'exposant nécessaire.

E - A la fin du masque uniquement, et suivi d'un entier
impose une notation scientifique, avec une largeur d'exposant imposée.

H - A la fin du masque, indique une représentation hexadécimale.

* - uniquement après une position 0 ou # au titre de modificateur "0 fois ou plus"

Ce format accepte par défaut un format équivalent à l'usage des fonctions d'impression ASCII "print" ou "echo" du language d'implémentation du processeur.

Le format par défaut pourra s'assimiler, en fonction de la nature de la variable, aux masques suivants :

pour une variable entière: #*

pour un nombre réel : #.#*E#*

4.2.4 Noms de variables prédéfinis

Certains noms de variables spéciaux sont prédéfinis, et servent à passer des informations particulières au processeur ESSI. Si une telle variable prédéfinie est reconnue, elle ne sera pas immédiatement substituée. Un traitement particulier peut être nécessaire ne résultant pas nécessairement en une substitution.

4.2.4.1 La variable %NULL%

Un processeur peut temporairement utiliser une variable %NULL% pour indiquer que l'entrée attendue n'existe pas dans la table d'entrée. cette variable sera ensuite éventuellement remplacée par la valeur de l'attribut NULL de l'appel de variable. La chaîne par défaut, en l'absence de toute autre spécification, vaut "" (la chaîne vide).

A noter que le signal %NULL% par déaut est équivalent à une entrée %NULL% de la table d'entrée dont la valeur vaudrait "".

La substitution finale d'une variable %NULL% évalue dans l'ordre :

  •  la valeur de l'attribut NULL de l'appel de variable
  •  une entrée "NULL" dans la table d'entrée
  •  la chaîne vide
4.2.4.2 La variable %ERROR%

Une opération de substitution peut échouer notemment lorsque l'attribut FORMAT est défini, et la représentation attendue ne peut être construite. Un autre cas d'erreur possible est lorsque le script associé au template n'est pas en mesure de calculer la valeur de l'entrée souhaîtée. Le contenu de la variable %ERROR% répondra au moins au format suivant :


code erreur : message d'erreur éventuel
4.2.4.3 Les variables %CGI::...%

Le groupe de variables %CGI::...% permet d'accéder directement aux variables standardisées de l'interface CGI telles que REMOTE_HOST, USER_AGENT, QUERY_STRING etc... Ceci permettra aux designers de pouvoir exploiter ces informations dans le document final, et aux développeurs de pouvoir effectuer des tests en bout de chaîne de leurs implémentations.

4.2.4.4 Les variables %ENV::...% d'environnement

Le groupe de variables %ENV::...% permet d'accéder directement aux autres variables d'environnement définies par le serveur. Ceci permettra aux designers de pouvoir exploiter ces informations dans le document final, et aux développeurs de pouvoir effectuer des tests en bout de chaîne de leurs implémentations.

4.2.4.4 Les variables %FORM::...% de formulaires

Le groupe de variables %FORM::...% permet d'accéder directement aux divers champs de formulaires à l'origine de la production du document. Ceci permettra aux designers de pouvoir exploiter ces informations dans le document final, et aux développeurs de pouvoir effectuer des tests en bout de chaîne de leurs implémentations.

4.2.5 Définition de variables à partir du DIML

4.2.5.1 Pourquoi ?

La possibilité de définir des variables à partir de l'interface DIML est utile lorsque l'on souhaite cacher certaines constructions au designer. Par exemple, considérez le cas d'une fonction CGI que l'on voudrait déclencher via une fonction Javascript pour éviter l'apparition de la chaîne de requête dans la ligne d'adresse du navigateur.

Le cas typique ci-dessus peut conduire à l'écriture suivante :

<HEAD>
<SCRIPT LANGUAGE=Javascript>
function FormLaunch(formname, actioncode)
{
document.form[formname].action.value = actioncode;
document.form[formname].submit();
}
</SCRIPT>
</HEAD>
...
<FORM NAME="CgiCall" ACTION="/cgi-bin/cgiCall.exe" METHOD=POST>
... éléments de formulaires ...
<INPUT TYPE=hidden NAME=action VALUE="defaultActionCode">
<A HREF="Javascript:FormLaunch('CgiCall', 'anAction')">
<IMG SRC="some_image.gif" BORDER=0></A>
</FORM>

Le pari fait par le DIML est que la plus grande partie de l'écriture servant au déclenchement CGI peut être totalement masqué sans nuire au besoin de souplesse dans le choix de l'apparence et du positionnement graphique. Les fonctions de définition de variables, ainsi que le procédé de "collecte des éléments d'en-tête", permettront cette amélioration.

Dans ce qui suit, on considérera à titre d'exemple la réduction du déclenchement de formulaire de la ligne :

<A HREF="Javascript:FormLaunch('CgiCall', 'anAction')">
<IMG SRC="some_image.gif" BORDER=0></A>

à l'expression :

<% %anAction()% %>

tout en donnant un moyen au designer de choisir l'image utilisée pour l'activateur :

<IMG SRC="some_image.gif" BORDER=0>
4.2.5.2 Définir des variables par définition de templates, l'attribut INLINE

La première solution consiste à définir un template "programmeur" suivant :

<TEMPLATE ID="anAction()">
<A HREF="Javascript:FormLaunch('CgiCall', 'anAction')">
<IMG SRC="<% %IMAGES_ROOT_UTL% %><% %anAction_image% %>" BORDER=0></A>
</TEMPLATE>

suite auquel on autoriserait que le designer puisse écrire le template suivant pour définir l'image :

<TEMPLATE ID="anAction_image" INLINE>
a_path/an_image.gif
</TEMPLATE>

L'attribut INLINE indique ici que le premier retour chariot (après la fermeture de la balise <TEMPLATE>) et le dernier retour chariot (avant la balise </TEMPLATE>) ne sont pas considérés comme faisant partie du fragment (et de ce fait, l'association <% %IMAGES_ROOT_UTL% %><% %anAction_image% %> ne sera pas coupée à la fin de la racine des images). Le fragment INLINE ci-dessus commence effectivement par un 'a' et se termine par un 'f'.

4.2.5.3 L'instruction SET

L'instruction SET est une manière explicite de passer des variables du côté design au côté codage. La syntaxe du passage de valeur est :

<%set %VARIABLE%="chaîne_délimitée" %>

Les variables deviennent accessibles à partir du point où l'instruction SET est évaluée. Leur valeur est accessible par un appel de variable simple :

<% %VARIABLE% %>

On pourra utiliser cette syntaxe pour redéfinir des curseurs de tableaux itératifs (par exemple par redéfinition de la variable table_name§I, premier indice du tableau table_name[] avec la version Perl du processeur ESSI).

L'exemple ci-avant serait alors écrit :

...

<FORM <% %CGI_CALL% %> >

... éléments de formulaire ...

<%set %CGI_CALL->IMAGE% = "http://some.host/some/path/some.file" >
<% %CGI_CALL->ANACTION()% %>

</FORM>

L'auteur de script définirait quant à lui :

  • Un template interne (soit directement par le source du script, soit dans un fichier DIML séparé)
    <TEMPLATE ID="ACTIVATOR_CGI_CALL" >
    <HEAD>
    <SCRIPT LANGUAGE=Javascript>
    function FormLaunch(formname, actioncode)
    {
    document.form[formname].action.value = actioncode;
    document.form[formname].submit();
    }
    </SCRIPT>
    </HEAD>
    <INPUT TYPE=hidden NAME=action VALUE="defaultActionCode">
    <A HREF="Javascript:FormLaunch('CgiCall')"><IMG SRC="<ANACTION_IMAGE% %>"
    BORDER=0></A>
    </TEMPLATE ID="ACTIVATOR_CGI_CALL" >
  • Le nom des appels DIML impliqués dans l'action CGI (ex. CGI_CALL et CGI_CALL->ANACTION()). Notez que nous avons choisi pour l'exemple une notation "orientée objet". rendue possible par la délimitation '%..%' des appels de variables.
  • Le nom des variables optionnelles (ex CGI_CALL->IMAGE) que le designer devra définir pour que le script puisse construire le fragment masqué.

Note 1 : Notez que l'instruction SET peut être utilisée à n'importe quel endroit du document source.

Note 2 : Les guillemets peuvent être omis si la chaîne_délimitée ne contient pas d'espaces.

Note 3 : La chaîne de définiton de la variable peut contenir des instructions ESSI.

4.2.5.4 L'instruction EVAL

Compatibilité : DIML 1.2

<%eval %VARIABLE%="fragment_diml_échappé" %>

L'instruction EVAL est une variante de l'instruction SET. Elle effectue le même traitement à un détail près qui peut se révéler de grande importance. Contrairement à l'instruction SET, l'instruction EVAL évalue la valeur affectée à la variable. Toutes les syntaxes DIML y sont alors résolues au moment de l'affectation.

Cette façon de faire à plusieurs implications.

  • La variable déclarée ainsi est plus rapîde à substituée, car les variables y sont résolues une seule fois.
  • La résolution des variables imbriquées ne s'effectuant qu'au moment de l'affectation, la valeur effective de cette nouvelle définition est insensible aux évolutions des appels DIML qu'elle peut contenir.
  • Ces variables peuvent être utilisables par des scripts invoqués sans risque de confusion (chemins d'accès de fichiers, URL, etc...).

4.3 Balises de structure

4.3.1 L'élément TEMPLATE

Les "templates" sont une des méthodes permettant d'optimiser le codage des pages Web, en considérant une page Internet comme l'assemblage de sous composants dont la sémantique propre peut être isolée du reste. Par exemple, l'index d'un catalogue produit comprendra typiquement une en-tête indiquant quelle est la société qui présente ce catalogue, puis pourra venir une barre de navigation globale pour la totalité du site. On peut également imaginer une "barre d'outils" permettant de manipuler les éléments du catalogue plus aisément. Enfin pourra apparaître la liste des éléments activés ou sélectionnés du catalogue, éventuellement triée.

Le HTML connaît une limitation majeure. En tant qu'application figée d'un document SGML, un document HTML contient une section d'en-tête HEAD, et un corps de document BODY. La seule façon d'échapper à cette structure est la définition de FRAMESETS qui divisent l'espace de mise en page en cadres distincts, chacun chargeant à son tour un document.

Il a été longuement éprouvé que la gestion par cadres conduisait rapidement a des problèmes de structure importants, surtout dans des systèmes dynamiques. Le seul grand intérêt de l'usage des FRAMESETS était le gain en bande passante de la totalité du réseau, dû à la persistance d'une grande partie de l'information dans le client lorsque seuls quelques éléments changent (voir l'attribut TARGET de l'élément A de la spécification HTML 3.0).

Les "templates" sont une nouvelle approche qui améliore la structuration des documents HTML et la réutilisabilité du code de présentation.

4.3.1.1 Définition de templates

Un template ESSI est défini comme étant un fragment de document HTML pouvant de plus accepter des instructions DIML. Toute construction du HTML peut être mise en "templates". Dans le cas extrême, un template pourrait même héberger la totalité d'une page. C'est implicitement dans ce sent que doit être envisagé un document DIML.

Un template ESSI est défini comme un élément SGML supplémentaire s'ajoutant aux éléments déjà définis par le HTML.

Une déclaration de template ESSI commence par une balise de début

<TEMPLATE>

et se termine par une balise de fin

</TEMPLATE> 

(comme c'est le cas pour de nombreuses balises HTML)

Une définition de template sera préférablement écrite en dehors de l'élément BODY d'un fichier DIML. Mais comme les fragments sont collectés avant l'exécution des substitutions, la présence de définitions de template dans le corps de document voire même dans l'en-tête ne posera pas de problème majeur. Un processeur ESSI correct ne laissera subsister aucun template dans le code HTML résultat.

On ne s'étonnera en rien que les déclarations de templates suivent strictement les règles de construction du SGML. Nous espérons qu'un jour, les appels ESSI pourraient être reconnus par les agents utilisateurs (qui sait...!).

4.3.1.2 Attributs

Un template est défini grace à l'attribut obligatoire ID qui assigne un nom au fragment. Ce nom est indispensable si ce fragment doit être appelé par une instruction d'injection. L'ID peut être n'importe quelle chaîne de caractères notée entre guillemets, ou un token unique non quoté.

L'attribut INLINE : Cf. définir des variables par définition de templates

4.3.1.3 Contenu de l'élément TEMPLATE

Le contenu d'un template peut être un simple fragment de code HTML, mais pourra aussi contenir une section d'en-tête HEAD. Si cette section est présente dans un fragment substitué, alors les éléments qu'elle contient seront collectés et ajoutés à l'en-tête principale du document. Le contenu de la section HEAD d'un template ne sera collecté qu'une fois, même si le template considéré est utilisé plus d'une fois dans le document. A titre d'exemple, le code DIML :

<HTML>
<HEAD> en-tête principale...</HEAD>
<BODY>
<% template file="#one" %>
<% template file="#one" %>
</BODY></HTML>
<TEMPLATE ID=one>
<HEAD>
<SCRIPT TYPE=Javascript>
function TemplateSpecificFunction()
{...}
</SCRIPT>
</HEAD>
code de corps HTML...
</TEMPLATE>

produirait,une fois substitué :

<HTML>
<HEAD> code d'en-tête principale...
<SCRIPT TYPE=Javascript>
function TemplateSpecificFunction()
{...}
</SCRIPT>
</HEAD>
<BODY>
code du corps...
code du corps (répétition)...
</BODY></HTML>

Cette spécification ne précise pas comment les éléments d'en-tête pourraient être indexés lorsque plusieurs templates différents définissent des éléments identiques.

Le contenu des templates peut à son tour contenir des instructions DIML d'injection de variables, ou des appels de templates, lesquels devront être récursivement remplacés pour constituer la chaîne résultat.

4.3.2 Appels de templates

4.3.2.1 Appels simples

Un template ESSI peut être rappelé à n'importe quel endroit d'un document DIML, y compris avant même sa définition. Un appel simple est une instruction DIML suivant la syntaxe :

... éléments d'en-tête </HEAD>
<BODY>
<H1>titre</H1>
<P><%template file=une_URI_de_fragment %>

L'attribut file, pointeur sur le template désiré, peut être écrit comme un fragment d'URI standard, localisant une ancre unique dans un document. C'est l'ID dans la définition du template qui sera prise en compte en tant qu'ancre. Par ce procédé, il devient possible d'intégrer des templates définis dans d'autres fichiers DIML. Voici des exemples de certaines situations classiques :

L'instruction suivante :

<%template file="#template_id" %>

Appelle un template défini quelque part dans le même fichier. L'instruction :

<%template file="chemin_relatif/un_document.diml#template_id" %>

va recherche un template d'ID "template_id" dans un fichier exprimé relativement au répertoire courant (celui du script d'alimentation, ou du document DIML maître, suivant la version de processeur).

Afin d'être conforme aux restrictions relatifs à l'attribut file de la norme SSI, il est convenu qu'il ne peut y apparaître le motif "..".

Pour pointer un document situé dans une arborescence autre que descendante, on utilisera l'attribut virtual, ainsi :

<%template virtual "../un_fichier.diml#un_template" %>

est valide.

Les attributs file ou virtual seront dans TOUS LES CAS des pointeurs sur des ressources locales. Il est illégal de tenter de pointer des ressources sur des hôtes différents, par exemple en utilisant un préfixe http: (c'est à dire qu'aucune mention de protocole ne de nom d'hôte ne doit y figurer).

4.3.2.2 Appels vectoriels

Les templates ont également été conçus comme un moyen pratique de définir des "motifs" HTML qui peuvent être répétés itérativement lors de la construction dynamique d'un document HTML.

Une page Web construite à partir de l'extraction d'une base de données, ou toute autre construction programmée fait souvent apparaître des éléments répétitifs. Ces répétitions sont la conséquence de l'itération dans l'algorithme utilisé pour construire la page.

A cette fin, la définition du DIML propose une syntaxe pour utiliser les templates comme motifs d'une construction itérative.

Par exemple, considérons la réponse d'un moteur de recherche à une requête sur un sujet précis. Dans la majorité des cas, les résultats de recherche sont extraits d'une base de données, et une page Web est construite à partir de ces résultats, donnant quelque chose comme :

<BODY>
<H1>Résultats de votre requête:</H1>
<TABLE>
   <TR WIDTH=400>
      <TD ALIGN=top WIDTH=40>1 -</TD><TD ALIGN=top WIDTH=400>
      <A HREF SRC="http://un.serveur.com/une/url/résultante.html">
      http://un.serveur.com/une/url/résultante.html</A>
	<BR><P><FONT COLOR="#FFFF80" SIZE=-1>
	Des informations associées à ce lien</FONT>
      </TD>
   </TR>
</TABLE></BODY></HTML>

Supposons maintenant que cette requête obtienne 10 réponses. La ligne <TR>...</TR> apparaîtra alors 10 fois, incrémentant le numéro de réponse dans la cellule gauche, et chaque lien et chauqe information respectivement à chaque réponse dans la cellule de droite.

Ceci pourrait alors être le résultat d'un appel vectoriel de template ESSI, lequel utiliserait des variables vectorielles :

<TEMPLATE ID="uneLigne">
<TR WIDTH=400>
   <TD ALIGN=top WIDTH=40><%%SEQUENCE[]%%> -</TD>
   <TD ALIGN=top WIDTH=400><A HREF SRC="<%%MATCHING_URL[]%%>">
   <%%MATCHING_URL[]%%></A>
   <BR><P><FONT COLOR="#FFFF80" SIZE=-1><%%MATCHING_INFO[]%%></FONT>
   </TD>
</TR>
</TEMPLATE>

Un appel vectoriel ressemble à un appel simple, auquel s'ajoute un attribut d'itération qui force explicitement la prise en compte de la nature vectorielle des variables tabulées qui y sont employées :

<%template file="#uneLigne" iterate=10 %>

Cette écriture force le processeur ESSI à incrémenter les indices associés aux tableaux utilisés dans le template, relativement à la profondeur d'imbrication du template (et à la dimension du tableau).

En général, le designer ne peut prévoir à l'avance combien d'enregistrements vont correspondre aux requêtes des utilisateurs. La syntaxe DIML ci-avant résout ce problème en indiquant explicitement le nombre d'itérations maximum que devra exécuter le processeur ESSI, même si les tables à explorer contiennent plus d'enregistrements. Pour maintenir la cohérence de ce modèle, on considérera que :

<%template file=#un_template %>

et

<%template file=#un_template iterate=1 %>

sont deux écritures équivalentes.

4.3.2.3 Outrepasser la limite du nombre maximum d'itérations

Dans certaines applications, la page de résultats doit afficher tous les enregistrements trouvés, quelque soient les conséquences sur la mise en page. La syntaxe suivante permet de généraliser le principe itératif précédent en introduisant la sémantique "tant qu'il y a des données".

<%template src="#a_template_anchor" iterate="*" %>
4.3.2.4 Règles pour la réutilisation de templates ou de variables

Comme il a été vu précédemment, les index courants des tableaux utilisés lors d'un appel vectoriel de template sont incrémentés DES QUE le template a été complètement évalué. Ceci a deux conséquences majeures :

  • Aucune itération des indices n'est effectuée pour tout appel vectoriel d'une table dans le corps principal d'un document DIML (hors de tout template).
  • Lorsqu'un template est rappelé dans la suite du document, les indices sont évalués à partir de la dernière valeur d'itération résultant de l'appel précédent.
  • Comme tous les indices repartent de 0 lorsque la page DIML est chargée, on ne pourra compter sur ces indices pour instaurer un principe de pagination des résultats (celle-ci devra être gérée explicitement par le script d'alimentation).
4.3.2.5 Appels vectoriels imbriqués

Comme l'imbrication d'appels vectoriels de templates est autorisé, il est utile de décrire comment devra se comporter un processeur opérationnel lorsque plusieurs appels vectoriels sont empilés. Voici un exemple d'une telle situation :

<TEMPLATE ID="boucle_interne">
<%%UNE_MATRICE[][]%%>
</TEMPLATE>
<TEMPLATE ID="boucle_externe">
<%template file="boucle_interne" iterate=3 %>
</TEMPLATE>
des éléments du corps principal...
<%template file="#boucle_externe" iterate=5 %>

Le résultat d'une telle construction est l'exploration d'une matrice carrée de 5 cellules par 3, dans laquelle chaque cellule sera le résultat de la substitution simple des variables UNE_MATRICE§0§0 à UNE_MATRICE§4§2.

La façon de travailler avec des tableaux multidimensionnels est exposée en annexe.

4.3.2.6 Simplification de l'accès aux templates locaux

Suite au commentaire d'un de mes étudiants, qui trouvait que la syntaxe d'appel des templates était quelque peu lourde, une syntaxe d'accès plus directe que la syntaxe complète <%template ... %> a été ajoutée à cette spécification.

Suite aux expérimentations sur le prototype du processeur, il est apparu fort utile que le contenu des templates collectés vienne s'ajouter à la structure d'entrée. Un template local est par cette technique assimilable à une variable ESSI simple, dont le nom correspond avec l'attribut ID de la déclaration du template.

La syntaxe DIML d'appel direct aux variables ESSI a donc été étendue dans le cas des templates locaux.

Par exemple, si un template local est défini ainsi :

<TEMPLATE ID="un_template">
du code DIML ...
</TEMPLATE>

alors son appel dans le corps principal pourra être écrit :

<%%un_template%%>

Si le template contient des appels à des variables vectorielles, alors on pourra le cas échéans appeller directement sa forme vectorielle :

<% %un_template[10]% %>

ou

<% %un_template[*]% %>

Note d'implémentation : Notez que les définitions d'entrées pour les templates collectés se font à l'intégration des données (elles ne sont donc pas connues par le script d'alimentation). Les programmeurs devront veiller à éviter toute collision de nom entre des entrées calculées par le script et celles résultant de la collecte des templates.

4.3.3 Import de templates externes

4.3.3.1 Distinction entre l'appel et l'import

Un appel de template, s'il est stipulé extérieur, réalise deux opérations :

  • Il charge le fragment de DIML du template dans la table locale de fragments
  • Il insère une instance de ce code à sa place

Dans certaines situations (voir la collecte d'éléments d'en-tête), il peut être nécessaire de dissocier les deux opérations, et de proposer un moyen simple d'importer le template dans la base locale de fragments disponibles, sans que celui-ci n'apparaisse nécessairement dans le document.

4.3.3.2 L'instruction IMPORT

L'instruction DIML %import permet d'importer un template externe dans la table de fragments et de collecter ses éléments d'en-tête. Sa syntaxe est similaire à l'appel de template explicite :

<%import file="un_chemin/un_fichier.diml#un_template" %>

L'import ciblé sur un template local n'a aucun intérêt. L'URI du template sera donc toujours une URI extérieure au fichier courant.

Pour pouvoir utiliser un fichier DIML comme une base de templates, la syntaxe précédente a été étendue à une version plus générale, permettant d'importer un groupe de templates (ou la totalité) d'un fichier. On utilisera les méta caractères :

  • * n'importe quel chaîne de n'importe quelle longueur y compris la chaîne vide
  • ? n'importe quel caractère éventuel
  • . un caractère quelconque
  • + le caractère précédent au moins une fois

pour composer le motif de recherche du nom de template. Par exemple, l'expression :

<%import file="un_chemin/un_fichier.diml#*" %>

importe la totalité des templates définis dans le fichier "un_fichier.diml" pointé.

4.3.4 Instructions d'arrêt

Les instructions d'arrêt servent à interrompre l'interprétation du DIML en cours de traitement du document. Elles se composent de deux instructions, l'instruction END et l'instruction STOP, qui ont des effets sensiblement différents.

4.3.4.1 L'instruction END

L'instruction end arrête définitivement l'exécution du DIML pour la page en cours et rend au serveur le tampon HTML constitué en l'état.

<%end %>

Cette instruction d'arrêt peut se révéler pratique pour stopper la production de la page lorsqu'un composant de sécurité détecte une erreur d'authentification. Voici un exemple de l'écriture d'un tel code :

<%if (%AUTH_OK% ne "true") %>
   <%%ACCESS_DENIED_MESSAGE%%>
   <%end %>
<%endif %>
4.3.4.2 L'instruction STOP

L'instruction stop est fondamentalement différente. Elle permet d'arrêter l'interprétation du DIML sur le niveau de substitution en cours (appel de template).

<%stop %>

Elle est en général utilisée dans une phase de débogage pour isoler une structure défaillante.

4.3.5 Instruction d'incrémentation

4.3.5.1 L'instruction BLIND

Depuis V 1.2

L'instruction blind est nouvelle depuis la version 1.2. Elle permet d'exécuter une variable DIML (un template ou un appel à un tableau) sans en intégrer la contrepartie au document. Par contre, tous les indices et variables de contexte concernées sont modifiées. Cette instruction permet surtout de traiter le problème suivant :

Soit le template affichant une ligne de prix d'un catalogue commercial :

<TEMPLATE ID="LISTE">
<%if (%TEST[]% ne "0") %>
<TR><TD><%%PRODUCT[]%%></TD><TD><%%TAB[]%%> Eur.</TD></TR>
<%else %>
<TR><TD><%%PRODUCT[]%%></TD><TD>N.C.</TD></TR>
<%endif %>
</TEMPLATE>

Affichant les deux tableaux ci-dessous à partir d'une base de données

<%%TEST§0%%> = 1 ; <%%TAB§0%%> = 12
<%%TEST§1%%> = 1 ; <%%TAB§1%%> = 13
<%%TEST§2%%> = 0 ; <%%TAB§2%%> = 0
<%%TEST§3%%> = 1 ; <%%TAB§3%%> = 15
<%%TEST§4%%> = 0 ; <%%TAB§4%%> = 0

4.4 Expressions

Le DIML dispose de quelques structures de contrôle, volontairement simplistes, car il n'est nullement l'intention de cette spécification de devenir un nouveau langage de script. Ces structures de contrôle simples permettent seulement de mieux gérer quelques écritures de pages complexes, sans pour cela remettre en cause la séparation entre le script et la présentation des données.

4.4.1 Structures conditionnelles

4.4.1.1 La structure IF...ELSIF...ELSE...ENDIF

Les instructions ESSI admettent une forme conditionnelle selon la structure "if ... elsif... else...endif". La complexité de ces structures n'est pas ici un objectif majeur. Elles ne sont proposées que par souci pratique, pour permettre une suffisante optimisation du code de présentation, par exemple lorsque des mises en formes sont très similaires à quelques détails près.

Par souci pratique, il existe deux formes de l'expression conditionnelle. La première, dite monoligne, intègre toutes les alternatives dans une seule instruction DIML. La deuxième, dite multiligne, permet de sélectionner un fragments de HTML parmi n suivant une structure IF..ELSIF...ELSE...ENDIF standard. La version monoligne est reconnaissable par la présence obligatoire du mot clef %endif en fin d'instruction.

4.4.1.2 La structure conditionnelle monoligne

La syntaxe monoligne d'une instruction conditionelle est :

<%if (condition) expression [%else expression] %endif %> 

dans laquelle les expressions sont des chaînes littérales, ou des appels à des variables ou à des templates, et condition une expression à valeur finale booléene.

Suivant le cas, la condition pourra utiliser la syntaxe du langage natif du processeur (par exemple pour la version PERL ou PHP).

L'expression peut être un appel à un template, qui provoquera l'insertion du template à la place de l'instruction si la condition est réalisée :

<%if (%TEST%) %template file="#the_template" %endif %>

Une expression peut être également un littéral HTML. Cette possibilité est proposée pour les cas où l'instruction conditionnelle sert à commuter entre deux expressions HTML courtes :

<%if (%TEST% == 0) "<HR WIDTH=30>" %else %ALTERNATIVE% %endif %> 

L'exemple ci-dessus montre que ces différentes formes peuvent être combinées à loisir.

Dans le cas d'une chaîne littérale, tout caractère pouvant influer sur l'interprétation du processeur devra être marqué en utilisant l'entité caractère SGML correspondante. Ainsi un guillemet littéral devra être noté &quot;. Les caractères à échapper impérativement sont :

  • ["] le guillemet.
  • [<] "inférieur à" si suivi d'un [%]
  • [>] "supérieur à" si précédé d'un [%]

Remarquez ici que le Processeur effectuera en effet une conversion d'entités caractères basée sur la liste d'entités définie dans la DTD HTML 4.0 (HTML 4.0 VF).

4.4.1.3 La structure conditionnelle multiligne

Par simple souci pratique, lorsque les alternatives sont constituées de portions HTML importantes, la syntaxe DIML propose une forme conditionelle similaire à celle proposée par les SSI (Server Side Include) :

<%if (condition) %>
du code HTML ...
<%elsif (condition) %>
une autre alternative...
<%else %>
encore du code...
<%endif %>

Ces structures multilignes peuvent être imbriquées entre elles ou avec des instructions conditionnelles monolignes selon les conventions usuelles de l'imbrication de telles structures.

4.4.1.4 Opérateurs et variables dans les conditions

Le DIML reconnait la plupart des opérateurs du C du PERL (pour la version PERL du processeur). A titre d'exemple :

==	égalité numérique
!= 	non égalité numérique
<		inférieur à (strictement)
>		supérieur à (strictement)
<=	inférieur ou égal
>=	supérieur ou égal
eq	identité (lexicographique)
lt	inférieur à (lexicographique)
gt 	supérieur à (lexicographique)
ne 	non identité (lexicographique)

La version PERL du processeur reconnait de plus les opérateurs d'expressions régulières du PERL :

=~	contient le motif
!~ 	ne contient pas le motif

En outre, les opérateurs logiques courants du C sont admis :

!		négation unaire
&&	ET logique
||	Ou logique
^		OU exclusif logique

Une condition peut citer toute variable définie au point de son évaluation.

4.4.1.5 Evolution future : La structure SWITCH...CASE

Pour étendre l'écriture de structures conditionnelles mutltibranches, la syntaxe DIML intégrera dans le futur la structure SWITCH...CASE, lorsqu'une variable joue le rôle de sélecteur. Cette structure n'apporte pas de fonctionnalité par rapport à la structure IF...ELSIF...ELSE...ENDIF, mais peut simplifier l'écriture dans certains cas.

La forme basique de cette structure sera :

<%switch (%SELECTOR%) %case text_value_expression %>
DIML statements...
<%case alternative_value_1 %>
DIML statements...
<%case alternative_value_2 %>
DIML statements...
<%case alternative_value_3 %>
DIML statements...
<%case alternative_value_4 %>
DIML statements...
<%case alternative_value_5 %>
DIML statements...
<%default %>
DIML default code...
<%endswitch%>

Une telle structure fonctionne comme celle du C ANSI, sauf qu'aucun signal "break;" ne devra être écrit. Le point de branchement "%endswitch" sera automatiquement atteint dès que l'alternative d'un "%case" a été exécutée.

Il est possible d'envisager d'autres extensions de structure de la syntaxe DIML, mais avant tout, on gardera à l'esprit que ce langage N'EST PAS DESTINE A DEVENIR UN LANGAGE DE PROGRAMMATION. Nous pensions simplement que les développeurs et les designers pourront à l'aide de ces quelques structures simplifier notablement l'encodage des documents Web, en réduisant le nombre de lignes de code écrites, et en gagnant en temps de développement global.

5. Structure des documents DIML

Ce chapitre discute des structures possibles de documents DIML. Y seront détaillées les distinctions à faire entre l'application stricte des règles syntaxiques, et les conséquences de certaines utilisations "hors cadre", et en essayant de définir quelles devraient être les réactions d'un processeur ESSI face à de telles extrapolations.

De plus, ce chapitre donnera quelques règles sur la façon d'interpréter le DIML.

5.1 Section principale

En tant qu'extension d'un document HTML, on admettra qu'un document DIML ne puisse être écrit qu'avec des entités HTML. De ce fait, tout document HTML est aussi un document DIML.

Comme conséquence principale sur la structure, tout document DIML peut contenir une section d'en-tête HEAD, un corps de document BODY ou une définition de cadres FRAMESET, puis un un certain nombre de définitions de TEMPLATES idéalement après la fermeture du corps par la balise </BODY>.

Il est admis, bien que non conseillé, que des définitions de templates puissent apparaître à tout endroit du document, y compris dans les sections HEAD et BODY d'un document.

Toute portion de DIML située à l'extérieur de toute définition de templates est considérée comme faisant partie de la section principale du document. La section principale est donc la trame DIML linéaire coinstituant l'ossature effective de la page Web. A l'inverse, toute portion de code située à l'intérieur de définitions de templates doit être considéré comme une brique d'information indépendante, utilisée par ailleurs ou à un autre moment lors de la constitution du document.

Pourront figurer dans une section principale autant d'instructions d'appel de variables ou de templates que nécessaire. Cette section principale devra être traitée comme un document HTML dès les substitutions effectuées.

Les tableaux seront explorés comme cette spécification le précise, à chaque fin d'évaluation d'un template en mode vectoriel.

5.2 Templates

Tout code situé entre les deux balises de définition d'un template est considéré comme ne faisant pas partie de la section principale du document et peut potentiellement ne jamais apparaître dans le document finalisé.

Le contenu des templates peut contenir des appels à des variables, ou des injections d'autres templates. Les concepteurs devront être particulièrement vigilants à ne pas créer d'injection circulaire, car aucune obligation n'est faite au Processeur de signaler ce cas de faute.

Les définitions de templates NE PEUVENT ETRE EN AUCUN CAS imbriquées - cela aurait peu de sens - bien qu'un template puisse en appeler un autre.

5.2.1 Appels vectoriels de variables dans une définition de template

Le principe récursif d'appel de variables d'entrée dans les définitions de templates rend possible l'appel vectoriel d'autres templates. Dans ce cadre, et combiné à l'usage de formes multidimentionnelles de certains tableaux, la gestion des indices peut paraître un peu difficile à appréhender. L'appendice 1 donne une explication détaillée sur ce point un peu délicat.

6. Alimentation de données

Le DIML ne résout pas à lui tout seul la construction de pages entièrement dynamiques. Il définit simplement des ancres où des données textuelles doivent être injectées dans une trame fixe. L'injection proprement dite est l'oeuvre d'une fonction exécutée sur le serveur, avant émission du document final.

Pour obtenir une solution complète, le processeur d'injection devra :

  • être une fonction de bibliothèque appelée par un script d'alimentation
  • être un exécutable autonome (binaire ou script) invoquant une fonction d'alimentation de données.

6.1 Appel par un script d'alimentation

Dans le cas de l'appel via un script d'alimentation, aucune syntaxe particulière n'est à prévoir. l'API du processeur d'injection se limitera à la structure d'entrée (tableau associatif dans la plupart des implémentations), des informations de localisation de la biliothèque, et du prototype d'appel du processeur.

Par exemple, pour la version module Perl dans le fichier ESSI.pm :

Structure d'entrée %main::ESSInput (tableau associatif)
Accès au module use ESSI;
Prototype &ESSI::processor(un_template);

6.1 Invocation d'une fonction d'alimentation

6.1.1 L'instruction INVOKE

Dans ce cas, le document DIML est directement interprété par le processeur autonome et devra indiquer à ce dernier le moyen de calculer effectivement les données d'entrée. Ceci est obtenu via l'instruction %invoke, dont le but est de définir, pour l'implémentation courante du processeur, la fonction à appeler pour créerla structure d'entrée. Les paramètres d'invocation dépendent fortement du langage natif du processeur, mais contiennent dans tous les cas :

  • La mention d'un nom de routine d'alimentation (fonction de bibliothèque, nom de fichier script, etc...)
  • Le nom du fichier contenant la représentation exécutable (ou linkable) de la routine.

Voici quelques exemples d'appels de l'instruction %invoke dans quelques cas de langages courants :

  • En C :
<%invoke script="E:\WINNT\System32\myapp.dll#feedmytemplate" %>
  • Pour la version PERL :
<%invoke script="E:\WINNT\System32\myapp.pm#feedmytemplate" %>

Notez que la commande d'invocation doit être effectuée avant tout utilisation d'une donnée calculée par le script d'alimentation. La structure d'entrée ne sera en effet complète que lorsque l'alimentation aura créé les entrées nécessaires à la construction de la page.

6.1.2 Fonction d'alimentation par défaut

En cas de defaut de précision du nom de la fonction (définie comme la partie fragmentaire de l'URI du code intégrable), le processeur tentera d'invoquer la fonction feed() dans le même espace de validité que le processeur (par exemple, en PERL : &ESSI::feed). Pour la version PERL, la fonction d'invocation pourra reconnaître la présence d'un script perl (.pl) et essayer d'en exécuter le contenu dans le contexte du processeur.

7 Optimisation et performances

Le traitement de pages complexes, ou générées à partir de multiples imbrications peut coûter cher en performances et en temps de calcul. L'une des grandes parties de ce coût est dû au fait que chaque substitution suppose une nouvelle évaluation complète de la variable à substituer. Ceci est d'autant plus vrai dans le modèle par défaut, dans lequel une variable peut être redéfinie à tout instant, par une instruction de définition SET.

Le DIML prévoit un certain nombre de syntaxes permettant dans une certaine mesure, d'optimiser la charge de calcul des pages, en évitant une recompilation systématique des variables. Cette option est particulièrement utile pour une page utilisant un grand nombre de fois des "templates" basés sur des variables stables.

7.1 L'attribut STATIC de l'élément TEMPLATE

Lorsqu'un template présente l'attribut booléen STATIC, alors celui-ci est compilé une seule fois en début du traitement. Le template est dit "statique". De ce fait, tout nouvel appel au template résultera en la même valeur, à l'exception près des variables vectorielles qui restent quant à elles intactes. La compilation des templates intervient une fois tous les templates extraits. Un template statique peut donc compter sur tous les templates du document pour sa compilation, mais ne pourra par contre pas prendre en compte les imports de fragments externes saufs ceux qui résulteraient d'une instruction d'importation dans leur propre contenu. Par exemple, dans le document :

<%import file="externals.dim#temp1" %>
<TEMPLATE ID="templocal1" STATIC>
some text ...
<% %temp1% %>
</TEMPLATE>

le template "templocal1" NE POURRA PAS bénéficier de l'importation du template "externals.dim#temp1", car les importations sont gérées postérieurement à la précompilation du template local. Par contre, dans :

<%import file="externals.dim#temp1" %>
<TEMPLATE ID="templocal1" STATIC>
some text ...
<%import file="externals.dim#temp2" %>
<% %temp2% %>
</TEMPLATE>

L'appel à "temp2" est légitime, car l'importation a pu s'effectuer dans le même phase que la compilation du template. Attention dans ce cas, la disponibilité du template externe "temp2" ne sera effective qu'après examen de l'instruction :

<%import file="externals.dim#temp2" %>

A. Appendices

Appendice 1 : Le modèle de tableaux multidimensionnel du DIML

Dans cet appendice sera détaillé et explicité le concept utilisé pour gérer l'exploration automatique des variables vectorielles.

A1.1 : Les indices implicites

Comme première règle absolue, le nombre et le nom des variables vectorielles ne peuvent être connus à l'avance, lorsque l'on ouvre un document DIML. Le caractère vectoriel d'une variable n'est constaté qu'à postériori, dès qu'une forme vectorielle est utilisée sur un nom symbolique. Ce n'est donc qu'au moment de la première utilisation d'un forme vectorielle qu'il est possible de mettre en place l'indice qui servira à l'exploration du vecteur. Tous les appels postérieurs à ce premier propoqueront une lecture de la variable à l'indice courant. La gestion des indices est donc implicite dans la définition du DIML.

Ceci a cependant deux conséquences majeures :

Tout d'abord, aucun nom symbolique dont la forme pourrait entrer en collision avec un indice construit à postériori par l'appel d'une forme vectorielle ne devra être utilisé. Dans la version Perl par exemple, toutes les terminaisons en "§I", "§C" et "§n" ou n est un entier positif sont TRES FORTEMENT DECONSEILLEES, car sont très fortement susceptibles de rentrer en collision avec des variables implicites servant à l'exploration des formes vectorielles.

La deuxième conséquence est que, à tout moment, il est possible d'influer sur l'exploration d'une forme vectorielle en prenant explicitement le contrôle de la variable d'indice associée.

A1.2 : Fonctionnement de l'exploration automatique

L'exploration automatique d'une forme vectorielle est directement liée à l'action des "templates". Un tableau ligne peut être appelé dans le corps principal ou dans un template. Par définition, c'est à la fin de l'examen du template que l'indice implicite du tableau est incrémenté.

         PRINCIPAL
               |
               +--------- VECTEUR[]                         Indice VECTEUR§I non incrémenté
               |                                            0 si premier appel
               +--------- TEMPLATE
                              |
                              +-------- VECTEUR[]           
                              +-------- VECTEUR1[]          Indice VECTEUR1§I initialisé à 0 
                              |
               +----------/TEMPLATE                         Indice VECTEUR§I incrémenté
               |                                            Indice VECTEUR1§I incrémenté

A1.3 : Les problèmes posés par l'exploration linéaire

Tant que la forme vectorielle reste linéaire (matrice à une ligne), la gestion des indices reste asez simple, car limitée à une incrémentation en sortie du template qui l'a invoquée. Reste cependant à savoir comment, en sortie de template, l'on pourra savoir quels indices vectoriels doivent être augmentés.

Lorsque la forme à plus d'une dimension, le problème est plus crucial. L'appel d'une forme multidimensionnelle est toujours réalisée à partir d'autant d'indices implicites que de dimensions de la forme. Ainsi, une forme de dimension 3 comme T[][][] fait appel à la définition de trois variables d'indice T§I, T§I§I, et T§I§I§I servant à l'exploration des trois dimensions du cube.

Appendice 2 : References

  • [HTML 4.0]
  • [SGML]
  • [XML]
  • [PHP]
  • [VBSCRIPT]
  • [PERL5.0]

Appendice 3 : Remerciements

Tous mes remerciements à toutes les personnes qui ont collaboré de près et de loin à cette étude, qui m'ont écouté divaguer pendant de longues semaines, qui ont eu la gentillesse de me décerner le diplôme du prof le plus "psychespace" de l'année (j'étais le seul candidat en lice !).

Remerciements particuliers à

  • Jean-Louis Campion
    Laboratoire de Recherches Appliquées - EISTI
    pour son assistance de tous les jours
  • William Godin
    EISTI - promo 2002
    pour sa collaboration et les séances de mise en oeuvre et de tests
  • Les étudiants de l'option NTIC
    EISTI - promo 2000
    pour leurs remarques, réflexions et commentaires
  • Nesim Fintz
    EISTI
    pour avoir permis au laboratoire d'exister
  • Francis Gibert & Sean Gough
    FGP / GS Sensors
    pour la patience et la confiance dont il nous ont fait preuve
  • Edouard Deslandes
    Pour ses marques d'intérêt répétées et ses encouragements
  • Nicolas Jourdan
    abcdrfc.free.fr
    Pour son intérêt, sa relecture et sa participation à la réflexion


    All material is copyleft V.G. FREMAUX (EISTI France) 1999 to 2003 except explicitly mentioned