I. Introduction▲
ASP.NET 2 arrive en grande pompe et une des nouveautés majeures annoncées s'appelle le page master(ing). Ce concept propose de mettre en œuvre l'héritage visuel de vos pages web en partant d'un modèle commun. Il ne reste plus qu'à compléter ce qui est spécifique à la page courante. Un exemple classique consiste à modéliser une page avec une zone d'entête, suivie d'un espace de contenu pour finir sur une zone bas de page.
Ce concept existe déjà depuis longtemps avec XMLRAD. Quelque soit la plateforme cible que vous allez choisir : Win32, Linux, Java ou .NET, la technique reste la même ce qui est loin d'être négligeable. Cette homogénéité indépendante des plateformes est possible, car tout repose sur des technologies standards et indépendantes : XML + XSLT.
Il est probable que vous devrez relire plusieurs fois ce tuto explicatif, car il détaille de façon assez précise les éléments mis en jeu. Ce ne sera pas forcément évident de recoller tous les morceaux à la première lecture… Je préfère prévenir. La récompense est qu'une fois tout ça assimilé, le concept vous paraîtra bien plus facile que vous ne pouviez l'imaginer !
II. Modèle de page standard▲
Lorsque l'on démarre le développement d'une nouvelle page, nous créons un nouveau XMLService. Un bon nombre d'assistants nous sont proposés. Chacun d'eux produit une page plus ou moins garnie, on peut citer les DataGrid, Formulaires d'édition, etc. Le modèle qui nous intéresse ici est accessible via l'assistant Divers / Fiche vide (screen_1).
Si vous allez au bout de cet assistant, voici le modèle de page qui est généré :
Pour une page vide, c'est déjà pas mal ! Malgré cet écran très plaisant, il ne correspond pas forcément à la structure de page de base de l'application web que vous allez mettre en chantier. Voici deux screenshots d'applications réalisées avec XMLRAD. Le premier repose sur le modèle de page vide proposé par défaut par XMLRAD. Le second s'appuie sur un modèle de page personnalisé, ce que nous allons apprendre à « modeler ».
III. Modèle de page standard : Étude interne▲
Nous allons commencer par étudier comment est conçu le modèle de page standard, matérialisé sous la forme d'un template xsl nommé xslc:Page.
Ce tutoriel n'a pas vocation à expliquer les différentes étapes du workflow de génération d'un écran, rappelons juste que des grappes de données XML sont initialisées, chargées et/ou générées à partir de sources multiples, et qu'un processeur XSLT parcourt ces données et exécute des actions de transformation de ces données. Le résultat de ces transformations est le plus souvent un flux HTML : la page web affichée par notre navigateur.
Quand on parle d'une page de base, on doit aussi évoquer les données de base sur lesquelles doit s'appuyer le template xslc:page ou celui que nous allons personnaliser.
Voyons donc les données XML disponibles par défaut pour le processeur xslt lors de l'invocation de notre page vide. Pour cela, sélectionnez le XMLService respectif, et cliquez sur le menu XML. Les données XML apparaissent sur la moitié droite de l'écran (screen_3) :
On retrouve :
- les XMLC_Params qui sont un mix de variables de fonctionnement de l'application ;
- les XMLC_Profile qui sont des données personnelles du profil de l'utilisateur courant ;
- les Aliases qui énumèrent un certain nombre de chemins ;
- les Locales qui constituent un dictionnaire de données (multilingue).
La racine de ces données XML est toujours <document>, ceci nous intéresse particulièrement ici.
Voyons maintenant comment notre page de base est générée au niveau du processeur xslt. Cliquez sur le menu XSL du XMLService pour visualiser le code xslt ou ouvrez-le dans un éditeur spécialisé tel que XMLSpy. La feuille xslt commence par matcher la racine du document xsl :
<?xml version="1.0"?>
<
xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xslc="http://xslcomponents.org/TR/WD-xslc"
>
<
xsl:import href="../../xslc.xsl"/
>
<
xsl:import href="../../Common.xsl"/
>
<
xsl:template match="/"
>
<
xsl:apply-templates select="document"/
>
<
/xsl:template
>
La présence de la balise document va déclencher le template document :
<
xsl:template match="document"
>
<
xsl:call-template name="xslc:Page"
>
<
xsl:with-param name="Title"
>
FormBase<
/xsl:with-param
>
<
xsl:with-param name="PageTitle"
>
<img align="
absmiddle
" src="
{$XMLC_PictosPath}ico_service.gif
"/>
FormBase
<
/xsl:with-param
>
<
xsl:with-param name="ToolbarButtonsLeft"
>
Le template document déclenche aussitôt un autre template nommé : xslc:Page avec un certain nombre de paramètres. Revoyons notre feuille xslt sous forme de vue grille arborescente (screen_4) :
Le modèle de page vide xslc:Page fourni en standard par XMLRAD est ici appelé avec les paramètres :
- Title
- PageTitle
- ToolbarButtonsLeft
- ToolbarButtonsRight
- ActionMenu
- Body
Allons voir d'un peu plus près ce template xslc:Page. Mais où est-il caché ?
Il est défini dans un fichier xslc.xsl. Ce fichier important regroupe quasiment tous les composants xsl (qui sont des templates xsl nommés) de l'environnement XMLRAD.
Il existe autant de copies de ce fichier que d'applications XMLRAD, autrement dit la librairie de composants xsl est propre à chaque application. On peut donc la modifier sans que cela ait des répercussions sur l'ensemble des applications ou sur l'environnement lui-même.
Ce fichier réside dans le sous-dossier \Bin\XML de l'application (screen_5) :
Voyons à quoi ressemble ce template xslc:Page… :
<
xsl:template name="xslc:Page"
>
<
xsl:param name="ActionMenu"/
>
<
xsl:param name="ActionMenuPosition"
>
<
xsl:choose
>
<
xsl:when test="/document/XMLC_Profile/XMLC_ActionMenuPosition"
>
………
………
………
<
xsl:param name="WaterMark"/
>
<
xsl:variable name="VBodyAttributes" select="msxsl:node-set($BodyAttributes)"/
>
<
xsl:variable name="VHtmlAttributes" select="msxsl:node-set($HtmlAttributes)"/
>
<
xsl:variable name="VToolbarButtonsLeft" select="msxsl:node-set($ToolbarButtonsLeft)"/
>
<
xsl:variable name="VToolbarButtonsRight" select="msxsl:node-set($ToolbarButtonsRight)"/
>
………
………
………
<HTML>
<
xsl:if test="$VHtmlAttributes"
>
<
xsl:copy-of select="$VHtmlAttributes/Attributes/@*"/
>
<
/xsl:if
>
<head>
<title>
<
xsl:value-of select="$Title"/
>
</title>
………
………
Ce template est très complet donc très long, on ne va parler que de certaines parties.
La première partie consiste en la déclaration de plusieurs paramètres, suivi des variables (xsl:variable). Ensuite commence la production de flux HTML, qui commence par la balise racine d'une page web : <HTML>. À partir de ce moment, des balises HTML vont être générées selon les paramètres et les variables du template xslc:Page.
Notez que ce template prend en compte les skins, on voit par exemple pas très loin après <HTML> la déclaration de <body> :
<body background="
{$XMLC_SkinPath}background.gif
" leftmargin="
0
" topmargin="
0
" rightmargin="
0
" bottommargin="
0
">
<
xsl:if test="$WaterMark != ''"
>
<
xsl:attribute name="style"
>
background-attachment:fixed;
background-image:url(<
xsl:value-of select="$WaterMark"/
>
);
background-position:bottom right; background-repeat:no-repeat
<
/xsl:attribute
>
IV. Les skins ?▲
Les skins permettent de personnaliser le visuel de vos écrans en fonction des paramètres d'application ou de l'utilisateur connecté. Le framework remonte le skin à utiliser dans <document><XMLC_Params><XMLC_Skin> (cf. notre grappe XML ci-dessus).
La variable $XMLC_SkinPath est déclarée en tête du fichier xslc.xsl de sorte que cette variable soit accessible à tous les templates xslt, qui peuvent s'appuyer dessus pour accéder à des ressources graphiques dans le dossier du skin respectif. Voici comment est déclarée la variable $XMLC_SkinPath :
<
xsl:variable name="XMLC_SkinPath"
>
<
xsl:value-of select="$XMLC_Portal"/
>
Skins/<
xsl:value-of select="/document/XMLC_Params/XMLC_Skin"/
>
/<
/xsl:variable
>
<
xsl:variable name="XMLC_PictosPath"
>
Elle représente le chemin d'accès d'un dossier respectif à un skin, racine des ressources graphiques de l'application. De fait, pour notre future page de base, on fera attention à bien préfixer les chemins des ressources graphiques par {$XMLC_SkinPath}.
V. Comment modifier le template xslc:Page ?▲
C'est une question délicate. En réalité la vraie question devrait être : faut-il modifier le template xslc:Page ? Ce n'est pas recommandé par l'éditeur, car ce template peut évoluer au fil des versions de XMLRAD, et rien ne garantit une compatibilité descendante du fait de vos modifications. Précisons que si on modifie le template, cela ne concerne que l'application en cours et pas l'ensemble des applications que vous développerez avec XMLRAD, car les fichiers templates xsl sont recopiés dans le répertoire de chaque application.
Pourtant, nous souhaitons modifier ce template, car notre objectif est de définir un master de page ! Alors que faire ? Soit on doit trouver une autre solution, soit on transgresse les recommandations tout en gardant à l'esprit les contraintes qui peuvent en découler. J'ai choisi ici la deuxième option, mais… :
Il existe cependant une solution alternative qui permet de ne pas toucher au xslc:Page ! C'est une solution plus propre, mais plus complexe à mettre en œuvre, donc elle fera l'objet d'un autre tutoriel qui sera la suite de ce que vous êtes en train de lire.
Revenons à nos moutons, on se demandait : Comment modifier le template xslc:Page ?
Il faut déjà se demander quels paramètres on veut continuer de prendre en compte, et le cas échéant bien les prendre en charge dans notre modèle. Par exemple, notre nouveau modèle aura-t-il besoin d'un ActionPanel ou pas ? Sinon alors on peut supprimer le bloc <xsl:param name=« ActionMenu »/>. Si on oublie d'enlever la déclaration du paramètre, ce n'est pas grave non plus, car si non utilisé il est simplement ignoré par le processeur xsl.
Une fois les choix de paramètres effectués, on tend ensuite vers de la conception HTML assortie de quelques injections de xslt. Il faut enfin se demander si on ne veut pas rajouter de paramètres supplémentaires à notre modèle, paramètres qu'on devra gérer nous même.
Il faut avoir à l'esprit que les autres assistants XMLService (autres que Divers / Page vide) font aussi appel à xslc:Page, mais ils ajoutent un contenu plus garni au paramètre Body. Pour cette raison, il est préférable parfois de conserver ce paramètre Body, car les autres assistants pourront insérer leur contenu dans votre modèle de page via ce paramètre Body.
Récapitulons :
- On fait le tri dans les paramètres pris en charge ou pas par notre modèle ;
- On conserve éventuellement le paramètre Body ;
- On définit notre nouveau modèle de page, dans lequel on prévoit un espace pour inclure le contenu du paramètre Body.
Exemple : maintenant, créons un modèle de page simple avec seulement deux paramètres :
- Le paramètre Body ;
- Un nouveau paramètre nommé Date (pour dire si on affiche la date du jour ou pas).
Ce modèle est le suivant : un espace pour le menu, un pour le contenu et un pour le bas de page. La date irait dans le bas de page. Nous choisissons des couleurs harmonieuses, de façon à bien distinguer chacune des parties de la page HTML (screen_6) :
Voici le code HTML correspondant :
<HTML>
<head>
<title></title>
</head>
<body>
<table cellpadding
=
"0"
cellspacing
=
"0"
height
=
"100%"
width
=
"100%"
style
=
"position:absolute;"
>
<tr>
<td width
=
"150px"
style
=
"background:yellow;"
>
Menus </td>
<td style
=
"background:#F09AC8;"
>
Contenu (Body) </td>
</tr>
<tr height
=
"100px"
style
=
"background:red;"
>
<td colspan
=
"2"
>
bas de page</td>
</tr>
</table>
</body>
</HTML>
Nous allons intégrer cette structure HTML à l'intérieur du template <xslc:Page>. On commence par éliminer tous les paramètres et variables pris en charge par l'ex template xslc:Page, sauf le paramètre Body :
Maintenant on remplace le corps HTML du template, le nouveau template xslc:Page devient :
<
xsl:template name="xslc:Page"
>
<
xsl:param name="Body"/
>
<HTML>
<head>
<title/>
</head>
<body>
<table cellpadding="
0
" cellspacing="
0
" height="
100%
" width="
100%
" style="
position:absolute;
">
<tr>
<td width="
150px
" style="
background:yellow;
">
Menus </td>
<td style="
background:#F09AC8;
">
<
xsl:copy-of select="$Body"/
>
</td>
</tr>
<tr height="
100px
" style="
background:red;
">
<td colspan="
2
">
bas de page</td>
</tr>
</table>
</body>
</HTML>
<
/xsl:template
>
Remarquez l'emplacement de l'instruction <xsl:copy-of select=« $Body »/> qui va copier le contenu du paramètre Body. Ça y est, vous avez personnalisé le composant « page vide ». Voyons le résultat (screen_9) :
Vous pouvez remarquer que le template xslc:Page produit le résultat escompté, et que l'onglet « FormBase » et l'espace visuel associé sont le résultat d'éléments passés au paramètre Body.
On peut ajouter que les paramètres « title », « PageTitle », « ToolbarButtonLeft », etc. n'ont plus besoin d'être spécifiés lors de l'appel à xslc:Page, car notre nouveau template ne les prend pas en charge.
On pourrait ajouter par exemple : un paramètre Date dans notre template, et injecter la valeur de ce paramètre à l'endroit spécifié :
<
xsl:template name="xslc:Page"
>
<
xsl:param name="Body"/
>
<
xsl:param name="Date"/
>
<HTML>
<head>
<title/>
</head>
<body>
<table cellpadding="
0
" cellspacing="
0
" height="
100%
" width="
100%
" style="
position:absolute;
">
<tr>
<td width="
150px
" style="
background:yellow;
">
Menus </td>
<td style="
background:#F09AC8;
">
<
xsl:copy-of select="$Body"/
>
</td>
</tr>
<tr height="
100px
" style="
background:red;
">
<td colspan="
2
">
<
xsl:value-of select="$Date"/
>
</td>
</tr>
</table>
</body>
</HTML>
<
/xsl:template
>
Si aucun paramètre Date n'est passé, aucune valeur ne sera insérée dans le bas de page.
VI. Conclusion▲
J'espère que ce tour n'a pas été trop compliqué, que vous avez pu entrevoir les possibilités que cette technique apportait, et que cela vous permettra de structurer vos prochaines applications en pensant toujours à ce concept de modèle de page.
N'hésitez pas à disserter et débattre de ce sujet sur le forum XMLRAD, mais aussi à me poser des questions directement.