Accueil
 chercher             Plan du site             Info (English version) 
L'histoire de XML s'écrit en ce moment même. XMLfr vous aide à la suivre et à en dégager les tendances.Les listes de discussions XMLfr sont à votre disposition pour réagir sur nos articles ou simplement poser une question.Si vous ètes passionnée(e) par XML, pourquoi ne pas en faire votre métier ?XMLfr n'est heureusement pas le seul site où l'on parle de XML. Découvrez les autres grâce à XMLfr et à l'ODP.Les partenaires grâce auxquels XMLfr peut se développer.Pour tout savoir sur XMLfr.XMLfr sans fil, c'est possible !Pour ceux qui veulent vraiment en savoir plus sur XML.L'index du site.
 Si vous vous posez une question, vous n'êtes peut-être pas le premier...Les traductions en français des bibles XML.Ces articles sont des références dans leur domaine.Tout ce qu'il faut savoir pour démarrer sur un sujet XML...


Du document à la page

Comme certains d'entre vous j'ai découvert HTML après avoir déjà réalisé plusieurs interfaces utilisateur ! Je dois le dire j'ai été déçu… Pendant des années j'ai essayé de garder la sacro-sainte indépendance des données et de la mise en forme pour découvrir subitement un langage qui mélangeait allégrement les deux. J'ai donc accueilli XSLT avec un grand intérêt. Enfin nous allions pouvoir appliquer sur le WEB les bons vieux principes !

Par Gilles Vandelle.
mardi 22 octobre 2002

Exemples à télécharger (fichier zip)

La découverte d'XSLT

Les premiers pas

Jusque là tout va bien. On réalise ses premiers " templates ", on joue avec les possibilités du langage, on formate les données pour différents types de visualisation allant de l'écran haute définition au téléphone cellulaire. Après l'excitation des premiers prototypes vient le moment de fabriquer une application professionnelle.

Les ingénieurs n'étant pas les meilleurs pour concevoir quelque chose d'intuitif la conception des applications modernes passe en générale par les mains d'un graphiste. Celui-ci ne se soucie en général guère des contraintes d'implémentation et c'est un bonne chose. Quand notre développeur commence à plancher sur les belles pages conçues par notre graphiste une question lui vient rapidement : " Comment vais-je pouvoir transformer ceci en templates ? "

Du concept à la réalisation

Nous voici donc au coeur du problème. La jolie page que notre développeur a maintenant en face de lui ne ressemble pas du tout au beaux prototypes réalisés précédemment. En général une sorte de menu se trouve en haut. Puis un contenu central souvent bordé par deux colonnes contenant des informations condensées et de liens vers d'autres pages. Comment peut-on s'y prendre pour respecter les principes d'indépendance et éviter la programmation élément par élément ?

Un Modèle dirigé pas les données

Beauté et contraintes

Le principe sous-jacent à XSLT veut que les données guide la présentation. En d'autres termes chaque élément de notre document XML va diriger la sélection du " template " qui " match " afin de mettre en forme son contenu. Ceci semble difficile à appliquer et la tentation de programmer comme on le ferait en ASP ou JSP (c'est à dire une page HTML qui inclue des données) est grande. Dans ce cas XSLT devient plutôt lourd et inapproprié.

Ce qu'il ne faut pas faire

A ce moment de mon petit récit un exemple semble le bien venu. Une fois n'est pas coutume commençons par l'exemple de ce qu'il faut éviter.

Prenons l'exemple classique du " shoping cart " et voici notre XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<Shoping>
 <Profile>
  <Name>Jean Dupond</Name>
 </Profile>
 <Cart>
  <Product code="212312" quantity="1" cost="49">
   <Book>
    <Category type="computer">Informatique</Category>
    <Title>XML Schemas</Title>
    <Author>EDV</Author>
    <Editor>O'Reilly</Editor>
   </Book>
  </Product>
  <Product code="343434" quantity="5" cost="250">
   <Soft>
    <Category type="development">Outil de développement</Category>
    <Name>XML Spy</Name>
    <Editor>Altova</Editor>
   </Soft>
  </Product>
 </Cart>
 <Recommended>
  <Book>
   <Category type="computer">Informatique</Category>
   <Title>XSLT</Title>
   <Author>Micheal Key</Author>
   <Editor>X</Editor>
  </Book>
  <Soft>
   <Category type="development">Outil de développement</Category>
   <Name>JBuilder</Name>
   <Editor>Borland</Editor>
  </Soft>
 </Recommended>
</Shoping>

Supposons que l'effet demandé est une colonne gauche avec les recommandations et une colonne centrale avec les produits du panier.

Il faut alors éviter de programmer la page comme ceci :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:template match="/">
  <html>
   <body>
    <table>
     <tr>
      <td>
       <table>
        <tr>
         <td>Conseils</td>
        </tr>
        <tr>
         <td>Livres</td>
        </tr>
        <xsl:for-each select="/Shoping/Recommended/Book">
         <tr>
          <td>
           <xsl:value-of select="Title"/>
          </td>
         </tr>
        </xsl:for-each>
        <tr>
         <td>Logiciels</td>
        </tr>
        <xsl:for-each select="/Shoping/Recommended/Soft">
         <tr>
          <td>
           <xsl:value-of select="Name"/>
          </td>
         </tr>
        </xsl:for-each>
       </table>
      </td>
      <td>
       <table>
        <tr>
         <td colspan="3">Mon panier</td>
        </tr>
        <tr>
         <td colspan="3">Livres</td>
        </tr>
        <xsl:for-each select="/Shoping/Cart/Product/Book">
         <tr>
          <td>
           <xsl:value-of select="../@quantity"/>
          </td>
          <td>
           <xsl:value-of select="Title"/>
          </td>
          <td>
           <xsl:value-of select="../@cost"/>
          </td>
         </tr>
        </xsl:for-each>
        <tr>
         <td colspan="3">Logiciels</td>
        </tr>
        <xsl:for-each select="/Shoping/Cart/Product/Soft">
         <tr>
          <td>
           <xsl:value-of select="../@quantity"/>
          </td>
          <td>
           <xsl:value-of select="Name"/>
          </td>
          <td>
           <xsl:value-of select="../@cost"/>
          </td>
         </tr>
        </xsl:for-each>
       </table>
      </td>
     </tr>
    </table>
   </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

Notez que j'omets volontairement tout attribut de formatage pour alléger le code.

Vous me direz que j'exagère un peu et qu'une bonne programmation XSLT utiliserait différents " template " pour " Book " et " Soft " ce qui pourrait donner :

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:template match="/">
  <html>
   <body>
    <table>
     <tr>
      <td>
       <table>
        <tr>
         <td>Conseils</td>
        </tr>
        <tr>
         <td>Livres</td>
        </tr>
        <xsl:apply-templates select="/Shoping/Recommended/Book"/>
        <tr>
         <td>Logiciels</td>
        </tr>
        <xsl:apply-templates select="/Shoping/Recommended/Soft"/>
       </table>
      </td>
      <td>
       <table>
        <tr>
         <td colspan="3">Mon panier</td>
        </tr>
        <tr>
         <td colspan="3">Livres</td>
        </tr>
        <xsl:apply-templates select="/Shoping/Cart/Product[Book]"/>
        <tr>
         <td colspan="3">Logiciels</td>
        </tr>
        <xsl:apply-templates select="/Shoping/Cart/Product[Soft]"/>
       </table>
      </td>
     </tr>
    </table>
   </body>
  </html>
 </xsl:template>
 <xsl:template match="Product">
  <tr>
   <td>
    <xsl:value-of select="@quantity"/>
   </td>
   <td>
    <xsl:apply-templates/>
   </td>
   <td>
    <xsl:value-of select="@cost"/>
   </td>
  </tr>
 </xsl:template>
 <xsl:template match="Book">
  <xsl:value-of select="Title"/>
 </xsl:template>
 <xsl:template match="Soft">
  <xsl:value-of select="Name"/>
 </xsl:template>
</xsl:stylesheet>
Les limites

Cette deuxième approche peu paraître plus satisfaisante mais elle fait apparaître un problème important : Les catégories " Livres " et " Logiciels " sont codées en dur ce qui ne laisse pas beaucoup de possibilités d'extension. Il faudrait pour cela soit ajouter un niveau de rupture dans l'XML mais ceci n'est pas toujours possible ( celui-ci pouvant provenir d'une source externe) soit déduire les niveaux de groupement par une programmation astucieuse mais ceci ne permet pas de contrôler l'ordre voulu par le département marketing : " les livres doivent apparaître en premier quelque soit l'ordre de sélection dans le panier " Diable j'aurais dû faire plombier….

L'approche descriptive

De quoi s'agit-il ?

Avant de changer de métier essayons donc de prendre les choses sous un angle différent. La liste des catégories est certainement connue de l'application. Certainement que l'on peut même l'obtenir dans un ordre qui plait au département marketing. Cette liste peut alors faire l'objet d'un document externe que nous référencerons par la fonction " document() " de XPath ou bien nous pouvons inclure notre document XML initial d'un niveau englobant qui dirige la présentation.

Voici un exemple d'XML avec notre nouvelle approche :

<?xml version="1.0" encoding="ISO-8859-1"?>
<Page>
 <Groups>
  <Group element="Book">Livres</Group>
  <Group element="Music">Musique</Group>
  <Group element="Soft">Logiciels</Group>
 </Groups>
 <Columns>
  <Column content="Recommended">Conseil</Column>
  <Column content="Cart">Mon Panier</Column>
 </Columns>
 <Shoping>
  <Profile>
   <Name>Jean Dupond</Name>
  </Profile>
  <Cart>
   <Product code="212312" quantity="1" cost="49">
    <Book>
     <Category type="computer">Informatique</Category>
     <Title>XML Schemas</Title>
     <Author>EDV</Author>
     <Editor>O'Reilly</Editor>
    </Book>
   </Product>
   <Product code="343434" quantity="5" cost="250">
    <Soft>
     <Category type="development">Outil de développement</Category>
     <Name>XML Spy</Name>
     <Editor>Altova</Editor>
    </Soft>
   </Product>
  </Cart>
  <Recommended>
   <Book>
    <Category type="computer">Informatique</Category>
    <Title>XSLT</Title>
    <Author>Micheal Key</Author>
    <Editor>X</Editor>
   </Book>
   <Soft>
    <Category type="development">Outil de développement</Category>
    <Name>JBuilder</Name>
    <Editor>Borland</Editor>
   </Soft>
  </Recommended>
 </Shoping>
</Page>

On peut noter qu'un niveau page est apparu. Dans ce niveau nous retrouvons notre élément " Shoping " mais aussi " Groups " qui permet de contrôler les groupes. Un code XSL correspondant peut être alors :

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:template match="/">
  <html>
   <body>
    <table>
     <tr>
      <td>
       <table>
        <xsl:apply-templates select="Page" mode="left"/>
       </table>
      </td>
      <td>
       <table>
        <xsl:apply-templates select="Page" mode="center"/>
       </table>
      </td>
      <td>
       <table>
        <xsl:apply-templates select="Page" mode="right"/>
       </table>
      </td>
     </tr>
    </table>
   </body>
  </html>
 </xsl:template>
 <xsl:template match="Page" mode="left"/>
 <xsl:template match="Page" mode="left"/>
 <xsl:template match="Page" mode="right"/>
</xsl:stylesheet>
Allons plus loin…

Nous venons d'ouvrir une option intéressante car les données commencent à reprendre l'initiative. Nous pouvons poursuivre en ajoutant de nouveaux éléments qui permettent de définir ce que nous souhaitons et comment nous voulons le voir.

Par exemple ajoutons :

<Columns>
<Column
content="Recommended">Conseil</Column>
<Column content="Cart">Mon
Panier</Column>
</Columns>

Cette fois ci je vous laisse le plaisir de changer l'XSLT pour s'adapter à ce nouvel élément. Nous pouvons comme cela enrichir l'exemple jusqu'à obtenir des possibilités d'adaptation intéressantes qui peuvent aller jusqu'à une présentation de type " portail ".

Est-ce contre-nature ?

Ce n'est pas du tout contre nature. Ici nous enrichissons les données de " meta-données " afin de conserver une présentation évolutive. Ceci est même une approche moderne et notamment utilisée dans le schéma XML du W3C : lire à ce sujet le livre d'Eric van der Vlist.

Jusqu'où aller ?

En fait pousser trop loin dans cette direction obligerait à ajouter un grand nombre d'éléments XML ce qui ne serait pas souhaitable. Une approche mixte peut permettre de choisir l'une ou l'autre des solutions selon les cas.

Approche Mixte

Un modèle de page en XSLT

L'idée de l'approche mixte est de fabriquer un modèle de page en utilisant XSLT. Ceci apporte deux avantages : d'une part nous n'avons pas à inventer de nouveaux éléments XML. D'autre part nous pouvons bénéficier de toute la puissance d'expression du langage. Toute l'astuce réside dans l'implémentation.

Comment l'implémenter ?

XSLT n'est certes pas un langage objet et n'a pas la prétention de le devenir. En fait pour ceux qui ont eu l'occasion d'apprendre PROLOG ils y trouveront beaucoup de similitudes. Pour implémenter un modèle de page réutilisable je propose une approche utilisant la surcharge sur les " templates " importés.

Nous définissons d'abord un fichier " PageModel.xsl " que nous importerons dans chaque page utilisant ce modèle. Ce modèle définit tout le cadre de la page et applique des " templates " prédéfinis à chaque endroit où on aura des éléments dirigés par les données. La feuille XSLT qui importe ce modèle va surcharger ces templates pour y ajouter les données propose à la page. Ceci semble bien abstrait je vous dois donc un exemple :

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:template match="/">
  <html>
   <body>
    <table>
     <tr>
      <td>
       <table>
        <xsl:apply-templates select="Page" mode="left"/>
       </table>
      </td>
      <td>
       <table>
        <xsl:apply-templates select="Page" mode="center"/>
       </table>
      </td>
      <td>
       <table>
        <xsl:apply-templates select="Page" mode="right"/>
       </table>
      </td>
     </tr>
    </table>
   </body>
  </html>
 </xsl:template>
 <xsl:template match="Page" mode="left"/>
 <xsl:template match="Page" mode="left"/>
 <xsl:template match="Page" mode="right"/>
</xsl:stylesheet>

Vous noterez que ce fichier est assez général pour être utilisé dans toute notre application. Il peut être importé dans une feuille du type :

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:import href="PageModel.xsl"/>
 <xsl:template match="Page" mode="left">
  <tr>
   <td>Conseils</td>
  </tr>
  <xsl:for-each select="/Page/Groups/Group">
   <xsl:if test="/Page/Shoping/Recommended/*[ name() = current()/@element]">
    <tr>
     <td>
      <xsl:apply-templates/>
     </td>
    </tr>
    <tr>
     <td>
      <xsl:apply-templates 
           select="/Page/Shoping/Recommended/*[name() = current()/@element]"/>
     </td>
    </tr>
   </xsl:if>
  </xsl:for-each>
 </xsl:template>
 <xsl:template match="Page" mode="center">
  <tr>
   <td colspan="3">Mon panier</td>
  </tr>
  <xsl:for-each select="/Page/Groups/Group">
   <xsl:if test="/Page/Shoping/Cart/Product/*[ name() = current()/@element]">
    <tr>
     <td colspan="3">
      <xsl:apply-templates/>
     </td>
    </tr>
    <tr>
     <td>
      <xsl:apply-templates 
           select="/Page/Shoping/Cart/Product/*[name() = current()/@element]"/>
     </td>
    </tr>
   </xsl:if>
  </xsl:for-each>
 </xsl:template>
 <xsl:template match="Product">
  <tr>
   <td>
    <xsl:value-of select="@quantity"/>
   </td>
   <td>
    <xsl:apply-templates/>
   </td>
   <td>
    <xsl:value-of select="@cost"/>
   </td>
  </tr>
 </xsl:template>
 <xsl:template match="Book">
  <xsl:value-of select="Title"/>
 </xsl:template>
 <xsl:template match="Soft">
  <xsl:value-of select="Name"/>
 </xsl:template>
</xsl:stylesheet>

Dans ce dernier cas le fichier PageModel.xsl remplace l'utilisation de " meta-données " et devient vraiment plus qu'une simple feuille de style mais vraiment un modèle de page.

Conclusion

Nous utilisons cette dernière solution dans le logiciel que nous développons. Ne croyez pas que nous soyons arrivés du premier coup à cette solution. Il nous a fallu plusieurs versions. Ce modèle nous apporte une grande flexibilité et nous a permis de faire facilement évoluer notre interface utilisateur. Je voulais vous en faire profiter.

Bon courage !

Autres articles:

Copyright 2002, Gilles Vandelle.


 

Mots clés.



L'histoire de XML s'écrit en ce moment même. XMLfr vous aide à la suivre et à en dégager les tendances.


Les documents publiés sur ce site le sont sous licence "Open Content"
Conception graphique
  l.henriot  

Conception, réalisation et hébergement
Questions ou commentaires
  redacteurs@xmlfr.org