I. La source XML

Tout d'abord, définissons la structure du forum :

forum.xml
Sélectionnez
<?xml version="1.0" encoding="UTF-8"?>
<forum>
    <topic title="Exemple de forum XSLT" date="15.04.2011" description="Ajoutez une description ici">
        <post date="15.04.2011" author="Diego">
            <description><![CDATA[
            Ce forum peut afficher n'importe quelle entité HTML
            ]]></description>
        </post>
        <post date="15.04.2011" author="Andrew">
            <description><![CDATA[
            À titre d'exemple, <b>gras</b>, <i>italique</i>, <u>souligné</u>, <a href="http://www.developpez.com">lien</a>, etc.
            ]]></description>
        </post>
        <post date="15.04.2011" author="James">
            <description><![CDATA[
            <p>Un paragraphe HTML <a href="http://www.developpez.com">avec un lien</a>.</p>
            ]]></description>
        </post>
        <post date="15.04.2011" author="John">
            <description><![CDATA[
            Bonjour le monde !
            ]]></description>
        </post>
        <post date="15.04.2011" author="Robert">
            <description><![CDATA[
            Un formidable forum, n'est-ce pas ?
            ]]></description>
        </post>
    </topic>
    <topic title="Exemple de discussion forum 2" date="16.04.2011" description="Description de la discussion 2">
        <post date="16.04.2011" author="Michael">
            <description><![CDATA[
            Message d'exemple 1
            ]]></description>
        </post>
        <post date="16.04.2011" author="William">
            <description><![CDATA[
            Message d'exemple 2
            ]]></description>
        </post>
        <post date="16.04.2011" author="David">
            <description><![CDATA[
            Message d'exemple 3
            ]]></description>
        </post>
    </topic>
    <topic title="Exemple de discussion forum 3" date="17.04.2011" description="Description de la discussion 3">
        <post date="17.04.2011" author="Charles">
            <description><![CDATA[
            Message d'exemple 3.1
            ]]></description>
        </post>
        <post date="17.04.2011" author="Joseph">
            <description><![CDATA[
            Message d'exemple 3.2
            ]]></description>
        </post>
    </topic>
</forum>

Le forum contient différentes discussions, chacune d'elles contenant un nombre variable de messages. Chaque message contient le nom de l'auteur, la date de publication et le texte lui-même (description) qui peut contenir du code HTML.

II. Le PHP

Voici le code PHP assez simple permettant d'effectuer les transformations XSL :

index.php
Sélectionnez
<?php

if (version_compare(phpversion(), "5.3.0", ">=")  == 1)
  error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
  error_reporting(E_ALL & ~E_NOTICE); 

// create DomDocument and load our forum
$xml = new DOMDocument;
$xml->load('forum.xml');

$xsl = new DOMDocument;

switch ($_POST['action']) {
    case 'posts':
        $xsl->load('xslt/posts.xslt'); // importing xslt
        $proc = new XSLTProcessor; // creating xslt processor
        $proc->importStyleSheet($xsl); // attaching xsl rules
        $proc->setParameter('', 'topic_id', (int)$_POST['i']); // we will set param for XSL
        break;
    default:
        $xsl->load('xslt/forum.xslt'); // importing xslt
        $proc = new XSLTProcessor; // creating xslt processor
        $proc->importStyleSheet($xsl); // attaching xsl rules
        break;
}

echo $proc->transformToXML($xml); // output

?>

Notez bien le switch case. Pour les réponses à une requête AJAX (lorsque l'on clique sur une discussion), j'utilise le premier case (quand action vaut posts). Pour déterminer quels messages je dois afficher ((filtre), je vais passer l'identifiant de la discussion (topic_id) au script XSL.

III. Le CSS

Voici les styles utilisés :

css/styles.css
Sélectionnez
body{background:#eee;font-family:Verdana, Helvetica, Arial, sans-serif;margin:0;padding:0}
.main{background:#FFF;width:698px;min-height:500px;overflow:hidden;border:1px #000 solid;margin:3.5em auto 2em;padding:1em 2em 2em}

p{margin:0;padding:0}
.forum{border:1px solid #B0BBCD}
.forum .header{color:#fff;background-color:#545F6F;padding:5px}
.forum .topic{border-bottom:2px solid #B0BBCD;background-color:#F3F2EF;padding:5px}
.forum .topic .desc{margin-left:30px;font-size:12px;color:#444}
.forum .topic .posts{border-top:1px solid #B0BBCD;display:none;margin-top:10px;padding:10px}
.forum .topic .posts .post{border-bottom:1px solid #B0BBCD;margin:5px}
.forum .post .date{font-size:10px;color:#444;text-align:right}

Il contient les styles du forum, des discussions, des messages, etc.

IV. Le JavaScript

Le dossier js/ contient le fichier jQuery (js/jquery.min.js) et

js/main.js
Sélectionnez
function loadPosts(obj, i) {
    $('.topic#'+i+' .posts').load('index.php',
      {action: 'posts', i: i},
      function() {
        $(this).fadeIn('slow');

        obj.unbind('click');
        obj.click(function(e) {
            $('.topic#'+i+' .posts').slideToggle('slow');
        });
      }
    );
}

$(function(){
    $('.topic').click(function() {
        loadPosts( $(this), $(this).attr('id') );
    });
});
Image personnelleNote du traducteur : le code JavaScript proposé repose sur la version 1.3.2 de jQuery qui est ancienne (l'article original date d'avril 2011).
Un code correspondant à une version plus récente de jQuery pourrait être :
 
Sélectionnez
function loadPosts(obj, i) {
    $('.posts', obj).load('index.php',
      {action: 'posts', i: i},
      function() {
        $(this).fadeIn('slow');

        obj.on('click', function() {
            $('.posts', this).slideToggle('slow');
        });
      }
    );
}

$(function(){
    $('.topic').one('click', function() {
        loadPosts( $(this), this.id );
    });
});
Notez en particulier l'utilisation des méthodes .on() et .off() pour gérer les événements ainsi que l'utilisation de .one() pour déclarer un événement à n'exécuter qu'une fois.
Ce code a été testé avec les versions 1.10.1 et 2.0.2 de jQuery.

Lorsque le DOM est chargé, j'affecte un événement clic aux discussions du forum. Ensuite, lorsque l'on clique sur une discussion, j'utilise $.load() pour charger les messages de cette discussion. J'en profite pour désactiver l'événement clic existant et je le remplace par une fonction qui va alterner l'affichage et le masquage des messages.

V. Le XSLT

Enfin, la délicatesse des règles XSLT :

xslt/forum.xslt
Sélectionnez
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes" /> 
    <xsl:template match="/">
        <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html></xsl:text>
        <html>
            <head>
                <script src="js/jquery.min.js"></script>
                <script src="js/main.js"></script>
                <link media="all" href="css/styles.css" rel="stylesheet"/>
                <title>Notre forum AJAX / XSLT</title>
            </head>
            <body>
                <div class="main">
                    <h2>Notre forum AJAX / XSLT</h2>
                    <div class="forum">
                        <div class="header">Discussions du Forum</div>
                        <xsl:for-each select="forum/topic">
                            <div class="topic">
                                <xsl:attribute name="id">
                                    <xsl:value-of select="position()"/>
                                </xsl:attribute>

                                <a class="top_link" href="javascript:void(0)">
                                    <xsl:value-of select="@title"/> (<xsl:value-of select="count(child::*)"/>)
                                </a>
                                <div class="desc">
                                    <xsl:value-of select="@description"/>
                                </div>
                                <div class="posts"></div>
                            </div>
                        </xsl:for-each>

                    </div>
                </div>
                <xsl:comment>Copyright : AndrewP</xsl:comment>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

Note du traducteur : le code proposé ici est légèrement différent de celui de l'auteur (et de celui de l'archive de l'exemple). Il a été traduit et le doctype utilisé pour le rendu HTML a été modifié. Notez à ce sujet l'astuce utilisée pour obtenir un doctype HTML5, seule façon de procéder actuellement à ma connaissance.

Comme vous pouvez le constater, nous générons ici uniquement la partie principale du forum avec uniquement les discussions. Nous chargerons les messages avec AJAX pour chaque discussion à l'aide de jQuery.

xslt/posts.xslt
Sélectionnez
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:for-each select="forum/topic[position() = $topic_id]/*">
            <div class="post">
                <xsl:attribute name="id">
                    <xsl:value-of select="position()"/>
                </xsl:attribute>
                <xsl:value-of select="description" disable-output-escaping="yes"/>
                <div class="date">
                    posté à <xsl:value-of select="@date"/> par <xsl:value-of select="@author"/>
                </div>
            </div>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Pour ce fichier, seule la traduction du texte a été effectuée.

Le second fichier XSL va servir à générer les messages pour la discussion demandée. J'espère que vous n'avez pas oublié que les messages sont récupérés avec AJAX. Nous avons passé la variable $topic_id depuis le fichier PHP (voir index.php). Nous n'affichons donc que les messages correspondant à la discussion souhaitée.

VI. Conclusion et remerciements

Vous pouvez voir une démo en ligne ou télécharger l'archive de l'exemple.

J'espère que l'exemple d'aujourd'hui vous a plu et que votre intérêt pour XSLT n'a pas diminué !

Cet article a été traduit et publié avec l'aimable autorisation d'Andrey Prikaznov, l'article original (How to easily make animated forums using XSLT and Ajaxy) peut être vu sur le site Script Tutorials.

Nous tenons à remercier ClaudeLELOUP pour sa relecture attentive de cet article.