ESSI_Resource : Script file "/home/groups/d/di/diml/htdocs/support/essitest_feed.pl" does not exist here at 15
Google Chercher dans diml.org
[ english ]

 Dernières infos
 Une application du composant  WCT_NEWS  
>> Haut de la page

Data Injection Markup Language

Document test et Tutorial DIML

Auteur: V.G. FREMAUX
E.I.S.T.I. / Cergy, France
Laboratoire de Recherches Appliquées / NTIC

Version: FR 1.1 / Septembre 2002, EN 1.1 / Septembre 2002

Autres documents

Spécification DIML (RFC locale) : essi_fr.dim

Tutoriel complet sur le DIML : accueil du tutoriel (en ligne)

Jeu de Test Exhaustif du DIML : accueil du tutoriel (en ligne)

Objet de ce document

Ce document est une démonstration effective du schéma d'injection de données DIML. Il décrit, explique et démontre les fonctionnalités et constructions sémantiques du processeur ESSI que nous avons choisi d'implémenter. Nous l'utilisons nous-mêmes pour mettre au point les fonctionalités de nos processeurs.

Le processeur ESSI interprètant les balises DIML, qui est démontré ici ,est écrit en PERL 5.0 sous Apache. Des versions futures sont prévues, sous la forme de librairies pour Php, ainsi qu'une version dll pour chargement sous Perl pour Windows via AutoLoad.pm.

Cette version a été testée sur plate-forme Linux et Windows, sous Apache et IIS, et peut être exploitée avec la distribution IISAPI d'ActivePerl&tm; (Cf ActivePerl)

On se référera au document essi_fr.dim pour une justification complète des syntaxes et une proposition de spécification.

Dans ce document, les parties apparaissant en bleu clair sont dynamiquement produites par le processeur.

Bref résumé du DIML

DIML est une solution nouvelle d'interface de développement qui permet une séparation totale des actions de design présentationnel et l'encodage logique de documents dynamiques.

Appliqué au Web, le modèle général choisi pour cette interface intègre deux flux d'informations entre partie visible (présentation / HTML) et partie cachée (calcul des information / script).

Une page Web est avant tout un document, et de ce fait présente de l'information à un utilisateur humain, selon un ensemble conséquent de règles de présentation plus ou moins complexes. Ces instructions de présentation n'ONT JAMAIS d'influence sur la sémantique originelle de l'information qu'elle présente. Elles agissent plutôt sur la manière dont le destinataire perçoit et interprète cette sémantique.

La plupart des règles de présentation peuvent être réduites à des "éléments SGML" qui contiennent l'information elle-même dans sa forme la plus simple (on parlera de "concepts nus"). Le flux d'information qui circule de l'application vers l'utilisateur peut alors être considéré comme la fusion de ces concepts nus et de l'ensemble des rèlges présentationnelles (les feuilles de style proposant une solution élégante pour cette fusion).
Les techniques d'injection de données du DIML proposent une manière simple de formaliser ce procédé.

Dans le sens inverse, de nombreux sites Web dynamiques proposant une forte interactivité utilisent le mécanisme d'hyperliens comme substitut d'activateurs d'une Interface Homme-Machine. A ce titre, des sémantiques doivent pouvoir circuler de la présentation vers la logique, tout en laissant le choix des ressources graphiques aux designers.
La solution DIML propose un moyen de passer ces informations au script, tout en masquant la partie "mécanique" du code, et en protégeant ainsi les mécanismes logiques d'altérations dramatiques.

Balises d'injection valides

L'injection d'une donnée simple <% %DATA1F% %> a pour résultat :

Les espaces entre les marqueurs d'instruction DIML et l'appel de variables peuvent être supprimés, on obtient alors une variable <%%COMPRESSEE%%> dont la substitution est:

Test de formes d'appel malformées ou incorrectes

Typiquement, une balise d'injection valide est constituée d'un token (au sens large), encadré de deux caractères %. La forme <% % ERRONEE % %> est invalide, bien que l'instruction DIML y soit clairement délimitée.
Ainsi le résultat de l'appel :

Une syntaxe <% % ERRONEE % %> 

est :

Une syntaxe

Toute instruction erronnée aboutit soit à une contrepartie nulle (substitution par une chaîne vide), soit à un signal d'erreur généré par le moteur DIML pour les instructions.

Le comportement par défaut du processeur pour l'appel de noms erronés (retourner une chaîne vide) peut être modifié :

<%%VARIABLE DEFAULT="<BR>Valeur par défaut</BR>" MINLENGTH="40"%%>

Ainsi pour l'appel d'une variable "VARIABLE" non définie, nous obtenons:


Valeur par défaut

Appels récursifs

L'exemple suivant montre comment le Processeur ESSI substitue récursivement des variables, tant qu'une forme substituée contient de nouvelles instructions DIML. L'essai qui suit appelle une variable <%%IMBRICANTE%%>, laquelle sera substituée par le fragment DIML :

un fragment DIML contenant une variable [<%%IMBRIQUEE%%>]

<%%IMBRIQUEE%%> sera alors à son tour substituée par la chaîne : "imbriquée". Le test donne :

Renvoi de variables au script

Dans certain cas, et en particulier lors de l'"encapsulation" de certaines syntaxes, il peut être utile de pouvoir passer certaines variables du côté présentation au coté script logique. On définit pour cela un "template", ou plus explicitement par l'instruction %set de la définition DIML. Ainsi pour l'appel de <%%NOUVELLE_ENTREE DEFAULT="Un appel erroné"%%> avant et après sa définition :

Avant
Un appel erroné
Definition <%set %NOUVELLE_ENTREE% = "une chaîne définie à la volée" %>
Après
une chaîne définie à la volée

Appel de templates

Un template est un fragment DIML indépendant du corps principal du document. L'inclusion du template dans le même document voire dans le corps est possible, mais, à moins d'une instruction d'injection spécifique, il ne sera pas considéré comme en faisant partie. Ainsi un document pourra définir des templates qui ne seront pas utilisés par ce même document (voire jamais).

Les templates peuvent être considérées comme des entités document secondaires, une implémentation rigoureuse plaçant leur définition à l'extérieur de l'entité <BODY>...</BODY>.
Selon le principe de robustesse, on fera en sorte qu'un Processeur ESSI admette les définitons de templates dans le corps même du document principal.

Le template suivant, défini par :

<TEMPLATE ID="unTemplateLocal">
Pemier essai d'injection d'un fragment DIML dans un document DIML
</TEMPLATE>

définit un template dont le nom entièrement spécifié est "dimltest_fr.dim#unTemplateLocal"

Un processeur conforme isole le template et stocke son contenu dans la base de templates. Les instructions DIML sont ensuite interprétées dans le corps de document, et entre autres, l'appel au template suivant :

<%template file="#unTemplateLocal"%>

Essayons maintenant :

Pemier essai d'injection d'un fragment DIML dans un document DIML

Si l'appel au template vise une définition dans un autre fichier, le processeur ouvrira le document cible et en extraira le template désigné :

<%template file="autrefichier.dim#unTemplateExterne"%>

produit :

Une phrase d'un template externe appelant une []

le source de autrefichier.dim

Récupération des éléments d'en-tête

Un template peut contenir une section <HEAD></HEAD> dans laquelle pourront figurer des scripts ou des informations META que ce template pourrait avoir à utiliser. Le processeur ESSI collecte toutes ces informations, en vue de reconstruire la section d'en-tête <HEAD> du document HTML final. Pour vérifier l'action du processeur, regardez le code source de ce même document.

Les lignes suivantes, incluses dans le document DIML à l'origine de ce document, provoquent l'inclusion de deux balises META dans son en-tête, ainsi qu'une petite fonction Javascript. Le code source de ce template serait :

<TEMPLATE ID="headedTemplate"%>
	<HEAD>
	<META NAME="meta1" VALUE="valeur1">
	<META NAME="meta2" VALUE="valeur2">
	<SCRIPT LANGUAGE=Javascript>
	function uneFonctionVoid()
		{
		}
	</SCRIPT>
	</HEAD>
	du HTML à insérer "in-line"...
</TEMPLATE>

Note : Le processeur établit un ordre dans la reconstruction de l'en-tête principale. Ceci est très important pour les scripts clients. La collecte réécrit d'abord les scripts collectés dans les templates, dans l'ordre de découverte de balises <TEMPLATE> et en respectant l'ordre intérieur des différentes sections <SCRIPT>. Les sections <SCRIPT> du document principal sont ajoutées à la fin.

Injection vectorielle

Le processeur ESSI fait bien plus qu'une simple substitution de données. Ce qui suit illustre comment pouvoir formuler des mises en pages complexes de tables issues de l'exploration de bases de données. Le premier exemple montre comment une donnée pourrait être incluse n fois en utilisant une syntaxe d'appel vectoriel :

<%%TABLE[10]%%>

dans laquelle %TABLE% est une variable contenant la mention "une ligne".

Voilà le résultat d'une telle syntaxe :


ESSI_Resource : Iteration target does not exist at line 51

Pour ce qui suit, on se reportera à l'appendice 1 de la spécification ESSI pour une discussion du modèle de tableaux en DIML.

Comme le contenu de la variable TABLE est lui-même analysé par le processeur ESSI (comme le définit l'appel récursif), son contenu est susceptible de contenir des expressions DIML. Celles-ci peuvent être des appels simples à des variables, mais aussi des "appels vectoriels auto-itératifs". Ces appels présentent une syntaxe tabulaire reconnaissable, indiquant éventuellement un décalage par rapport à la position courante dans la matrice de valeurs associée :

TABULE[] ou TABULE[-3]

Ces appels vectoriels apparaîtront le plus souvent dans des templates, définissant alors un "motif". Mais il est tout à fait admis qu'un corps principal puisse appeler cette forme. Le résultat de l'appel est alors le contenu de l'élément de la matrice de données source à l'indice courant. Juste avant le début de l'analyse d'un fichier DIML, aucun pointeur de table n'est défini. On les supposera tous égaux à 0.

Injection vectorielle dans un corps de document

Le premier appel effectif d'une variable %TABULE[]% dans le corps principal de document injectera l'entrée de clef TABULE§0. Les appels suivants de la forme %TABULE[]% dans le corps de document renverront toujours la même valeur, car aucune incrémentation automatique d'indice ne s'effectue hors du cadre de l'appel de template.

Ainsi trois appel de la même variable TABLE1D dans le corps principal de ce document :

<% %TABLE1D[]% %>
<% %TABLE1D[]% %>
<% %TABLE1D[]% %>

produisent :



Comme attendu, l'itération ne s'est pas produite, les trois appels se suivant dans le même segment principal de DIML sans aucun appel de template intermédiaire.

Ce principe, suivant les mêmes règles, sera étendu à des dimensions multiples. Ainsi pour le cas d'un appel tabulaire à une matrice de variables :

TABLE2D§0§0 : "coin gauche supérieur" TABLE2D§0§1 : "coin droit supérieur"
TABLE2D§1§0 : "coin gauche inférieur" TABLE2D§1§1 : "coin droit inférieur"

il suffira d'écrire :

<% %TABLE2D[][]% %>

pour récupérer la chaîne :

au titre de l'entrée %TABLE2D§0§0% de la structure d'entrée ESSInput.
Notez que le premier appel initialise les deux indices à 0, et que nous sommes toujours dans le corps principal de document, et qu'ainsi aucun des indices ne sera altéré. Par conséquent, Le prochain appel de la variable %TABLE2D[][]% donnera le même résultat "coin gauche supérieur", tant que l'action d'un template ne vient pas altérer ses indices.

Injection vectorielle dans un contexte de template

A l'inverse, lorsque l'appel est inclus dans un template, chaque appel au template provoquera l'évolution des indices des vecteurs ou matrices qui y sont appelés. Considérons le document contenant la définition de template suivante :

<TEMPLATE ID="Iteratif">
	du HTML ...
	un appel vectoriel : <%%TABLE1D[]%%>
	du HTML...
</TEMPLATE>

La définition ci-dessus inclut implicitement le mécanisme d'évolution des indices dans la table unidimensionnelle %TAB1D% à chaque activation du template, parcourant ainsi les variables d'entrée %TABLE1D§0% à %TABLE1D§n% si n+1 templates sont appelés.

Tout appel vectoriel au template :

<%template file="#Iteratif" iterate=4 %>

provoquera l'injection de 4 copies du template, avec auto-incrémentation de la variable d'index pour les vecteurs cités dans le template (ici, %TABLE1D%). Dans le cas d'un template défini dans le même fichier que l'appel, ou template "local", l'écriture suivante serait équivalente :

<% %Iteratif[4]% %>

Voici les résultats obtenus dans les deux cas :

Instruction "%template..." explicite Appel implicite

Du code HTML...
une balise d'injection vectorielle :
du HTML...

Du code HTML...
une balise d'injection vectorielle :
du HTML...

Du code HTML...
une balise d'injection vectorielle :
du HTML...

Du code HTML...
une balise d'injection vectorielle :
du HTML...

Du code HTML...
une balise d'injection vectorielle :
du HTML...

Du code HTML...
une balise d'injection vectorielle :
du HTML...

Du code HTML...
une balise d'injection vectorielle :
du HTML...

Du code HTML...
une balise d'injection vectorielle :
du HTML...

Notez que le second appel continue l'itération là où l'avait laissée le premier appel.

Structures conditionnelles

Le DIML n'est pas (rassurez-vous) destiné à devenir un (autre) langage de programmation de page. D'autres langages existants remplissent déjà fort bien cette fonction.

Cependant, un minimum de structures conditionnelles permet de simplifier l'implementation dans de nombreuses situations. Bien que la résolution de constructions complexes s'effectue de préférence au niveau du code script serveur, puis aboutit à la sélection d'un modèle DIML simple pour la sortie, l'implémentation de ces éléments conditionnels élémentaires ne pourra que rendre le DIML plus souple.

Le DIML définit deux formes de structures conditionnelles. La première est composée d'une unique instruction DIML, la seconde s'intercalant dans le flux DIML :

Structures compactes
<%if (condition) ... %endif %>
<%if (condition) ... %else ... %endif %>

Constructions multilignes
<%if (condition) %>
...
<%endif %>
<%if (condition) %>
...
<%else %>
...
<%endif %>
<%if (condition) %>
...
<%elsif (condition) %>
...
<%else %>
...
<%endif %>

Instructions conditionnelles compactes

Les instructions conditionnelles compactes seront en général utilisées pour effectuer un choix simple entre deux variables à injecter (ou templates) :

<%if (%NEXT% ne "") %NEXT_IMG_CALL% %else %PREV_IMG_CALL% %endif %>

appelant le template :

<TEMPLATE ID="PREV_IMG_CALL">
<IMG SRC="<%%IMAGES_ROOT_URL%%>prev.gif">
lt;/TEMPLATE>

en vertu de l'absence en ce point du document de toute définition de la variable %NEXT% (remarquez ici l'usage d'une variable DIML pour paramétrer le chemin de base de l'accès aux ressources graphiques).

Notez aussi que la syntaxe de la condition dépendra fortement de l'implémentation du processeur. La version Perl accepte n'importe quelle expression conditionnelle Perl (c'est à dire n'importe quelle expression EXPR à valeur résultante booléène pouvant être le résultat de la fonction eval(EXPR)). On pourra y invoquer des variables DIML selon la syntaxe DIML %token_variable%.

La clause ELSE peut être omise, et des structures élémentaires IF...ENDIF peuvent donc être utilisées :

<%if (%NEXT% eq "") %NEXT_IMG_CALL% %endif %>

appelle finalement le template :

<TEMPLATE ID="NEXT_IMG_CALL">
<IMG SRC="<%%IMAGES_ROOT_URL%%>next.gif">
</TEMPLATE>

Notez que chaque alternative peut être une instruction DIML à part entière, sous condition d'être dûment formatée (encadrée par des %). Tout % littéral contenu dans l'instruction devra alors être échappé par son entité caractère SGML correspondante.

Structures conditionnelles multilignes

Pour plus de commodité, une syntaxe proche des instructions SSI a été ajoutée à la définition du DIML, servant avantageusement à la sélection entre deux portions importantes de code DIML. Cette construction conditionnelle utilise des instructions DIML courtes pour délimiter les différents blocs alternatifs. Les structures conditionnelles de ce type peuvent être imbriquées indéfiniement (prenez simplement garde à l'influence de ces imbiractions sur les performances !), et des formes compactes peuvent apparaître à tout endroit à l'intérieur ou à l'extérieur de ces structures. Il sera du devoir du processeur de vérifier l'intégrité conditionnelle de tout segment à substituer.

Note importante : bien que la syntaxe DIML soit un outil puissant de composition et structuration de code présentationnel, elle subit néanmoins une limite majeure quant au traitement conditionnel : l'intégrité conditionnelle doit être vérifiée dans chaque frament DIML, AVANT toute opération locale de substitution. De ce fait et EN AUCUNE MESURE l'on ne pourra compter sur une substitution future pour compléter la construction correcte d'une structure conditionnelle.

L'intégrité interdit donc les :

  • ENDIF sans IF
  • ELSE sans IF
  • ELSIF sans IF
  • ELSE après un ELSE
  • ELSIF après un ELSE
  • structures conditionnelles incomplètes (niveau d'imbrication non nul en fin de document)

Un exemple de structure conditionnelle simple :

<%if (%TEST% eq "un") %>
première alternative
<%elsif (%TEST% eq "deux") %>
seconde alternative
<%else %>
aucune des deux, mais<BR>
<%if (%TEST% eq "trois") %>
première sous-alternative
<%else %>
seconde sous-alternative
<%endif %>
<%endif %>

Un exemple de structure conditionnelle simple :

<%if (%TEST% eq "un") %>
première alternative
<%elsif (%TEST% eq "deux") %>
seconde alternative
<%else %>
aucune des deux, mais<BR>
   <%if (%TEST% eq "trois") %>
   première sous-alternative
   <%else %>
   seconde sous-alternative
  <%endif %>
<%endif %>

présente 4 résultats distincts dans la table ci-dessous, suivant que %TEXT% vaut 'un', 'deux', 'trois' or 'quatre'.


TEST Valeur résultante
un première alternative
deux seconde alternative
trois aucune des deux, mais
première sous-alternative
quatre aucune des deux, mais
seconde sous-alternative

Invocation des scripts d'alimentation

Un document DIML utilise un certain nombre de sources de données pour construire le document terminal. Certaines de ces sources sont prédéfinies, telles que :

  • Les données des formulaires reçues par l'interface CGI
  • Les variables d'environment
  • Les indices de toutes les formes vectorielles invoquées (basées sur les identificateurs des vecteurs)
  • Les tailles dynamiques des formes vectorielles (basées sur les identificateurs des vecteurs)
  • Des pragmas du processeur ESSI (variables internes)

D'autres sources, telles que des résultats de calcul du script lui-même, ou des données obtenues par extraction de bases de données ou de source de données XML, sont totalement dépendantes du contexte.

L'implémentation du processeur ESSI procure deux moyens essentiels pour invoquer l'alimentation en données d'un document DIML :

Implémentation dite du "Processeur esclave"

Dans cette implémentation, le processeur ESSI est une fonction de librairie, appelée par un script d'alimentation faisant office de script principal. C'est de cette façon qu'est composé le présent document. Le script d'alimentation principal se contente alors de préparer un tableau associatif d'interface, et le passe au Processeur ESSI (comme une variable gobale, une référence ou un objet, selon l'implémentation).

La construction de la page sera effectuée selon le principe suivant :

Implémentation "Processeur maître" avec invocation de script d'alimentation

Cette implémentation permet l'invocation directe d'un document DIML sur le serveur, selon le principe :

Le source DIML devra alors inclure une instruction %invoke pour exécuter dynamiquement la portion de script d'alimentation en données.

Ce qui suit est une démonstration de cette technique, et appelle un script d'alimentation complémentaire "testfeed.pl" définissant deux variables "EXTERNE1" et "EXTERNE2".

Avant invocation du script <%%EXTERNE1%%> = ""
<%%EXTERNE2%%> = ""
"Invoke"
<%invoke script="&lt;% %SCRIPT_ROOT_URL% %&gt;testfeed.pl" %>

ESSI_Resource : Script file "/home/groups/d/di/diml/htdocs/support/testfeed.pl" does not exist here at 101
Après invocation <%%EXTERNE1%%> = ""
<%%EXTERNE2%%> = ""

Notez les entités SGML '&lt;' et '&gt;' utilisées comme échappement des caractères '<' et '>' à l'intérieur du chemin d'accès de l'appel au script.

License

Copyright (C) 2000 Valery Fremaux for EISTI (vf@eisti.fr), Business Copyright (C) 2000 ADITRI

Le Processeur ESSI est un prototype logiciel libre; vous pouvez le redistribuer et/ou le modifier dans les termes de la GNU General Public License telle que publiée par la Free Software Foundation; en version 2, ou (selon votre choix) toute version ultérieure.

Ce programe est distribué dans l'espoir qu'il serait utile, mais SANS AUCUNE FORME DE GARANTIE;

Pour toute copie de la GNU General Public License, écrivez à la Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

La spécification DIML est d'accès libre, c'est-à-dire, ne nécesite aucune license ni ne pourra prévaloir à aucun versement de royalties lorsqu'implémentée et diffusée dans le cadre de la license GNU. L'usage de l'acronyme "DIML" et des symboles associés est libre, mais implique l'acceptation complète de la spécification DIML, à l'exception de quelques tolérances dont :

  • La syntaxe de formatage des données, à condition que la substitution par défaut reste la chaîne vide.
  • le mécanisme d'invocation n'est pas obligatoire, bien que fortement recommandé
  • Les attributs d'optimisation (STATIC) des templates
  • L'instruction STOP

L'implémentation minimale comprend :

  • Les éléments TEMPLATE avec l'attribut INLINE
  • Toute forme d'injection de donnée (scalaire et vectorielle)
  • Instructions conditionnelles (monoligne et multilinge)
  • Instruction SET
  • Apples explicites de templates, internes et externes

En complément des dispositions précédentes, et en cas d'évolution de la license précitée, la présente restreint l'application de la license libre à un usage strictement non commercial. Toute demande d'exploitation, ou d'utilisation comme partie d'un produit commercial pourra être adressé à :

ADITRI Software Licensing
c/o EISTI Applied Research LaboratorY
Avenue du parc
95011 CERGY CEDEX
FRANCE

ou par email à early-licensing@eisti.fr


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