JeuWeb - Crée ton jeu par navigateur
Un sommaire et son contenu en XML/XSL - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Un sommaire et son contenu en XML/XSL (/showthread.php?tid=862)



Un sommaire et son contenu en XML/XSL - Roworll - 23-02-2007

Difficile de faire un véritable Tutorial sur XSL.
Je vais donc commencer par une simple démonstration commentée.

L'objectif est de réaliser une aide/mini FAQ en utilisant le XML/XSL

Passons rapidement sur la partie PHP de l'application
Code PHP :
<?php
// J'utilise de l'UTF-8 par habitude et pour des raisons de compatibilitée caractéres spéciaux
$xml='<?xml version="1.0" encoding="UTF-8" ?>';
// Cette ligne va indiquer ou trouver le XSL pour la transformation
$xml.='<?xml-stylesheet type="text/xsl" href="xsl/faq.xsl"?>';
// Ajoute au coutenu de la page le fichier XML qui contient l'aide
$xml.=file_get_contents('xml/faq.xml');
//Envoie d'un Header XML
header('content-type: text/xml');
//Affichage du contenu de la chaine générée
echo $xml;
?>
Le but de ce code est de renvoyer une page au format XML contenant les informations que l'on souhaite afficher.

Le XML doit être structuré pour être exploité correctement par le XSL.
Mon document XML a pour racine le noeud <topics> et contient plusieurs éléments fils <topic> défini comme suit.
Code PHP :
<?php 
<topics>
...
<
topic parent="2" id="3">
<
titre>Races</titre>
</
topic>
<
topic parent="3" id="4">
<
titre>Elfes</titre>
<
data>blablabla</data>
</
topic>
<
topic parent="3" id="5">
<
titre>Nains</titre>
<
data>blablabla</data>
</
topic>
...
</
topics>
Un topic a donc deux attributs.
- Un Parent qui indique a quelle noeud de l'arborescence il appartient.
- un ID qui permet de le repérer et de connaître les éléments qui lui sont rattachés
Chaque ID se doit d'être unique. Dans le cas contraire, le XSL aura du mal a organiser les informations correctement.
Chaque topic peut posseder aussi deux éléments fils
- un Titre qui servira a afficher l'index
- un data qui contiendra les informations relatives au titre. Le Data peut contenir du code HTML pour une meilleure mise en page.

Passons maintenant au coeur du systéme : le XSL

Code PHP :
<?xml version="1.0" encoding="UTF-8" ?>
<!--
<?
//un faux tag en commentaire pour mettre de la couleur dans cet exemple...
//Totalement inutile evidemment dans une version réelle ^^
-->
<
xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<
xsl:output method="html" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" />
<!--
/*Les lignes précédentes contiennent des informations sur le rendu utilisés par le processeur XSL
On peut y préciser l'encodage, la version du processeur XSLT à utiliser, le DOCTYPE, etc
*/
-->


<!--
/*
Ici commence le processing du XML.
Le Template match="/" indique que les traitement a suivre vont s'appliquer à partir de la racine du document.
*/
-->

<
xsl:template match="/">
<!--
/*
/*Le XSL va ressortir du HTML. Les déclarations classiques sont donc essentielles pour sortir un code propre.
A noter que le format de sortie sera défini en fonction des valeurs spécifiées dans xsl:stylesheet et xsl:output*/
*/-->
<
html>
<
head>
<!--
/* pour ne pas trop compliquer, tous les styles sont inclus dans la page */-->
<
style>
html {font-family:verdana, helvetica, sans-serif; font-size:11px;}
ul.root {list-style-type:none; padding-left:0px; margin-top:0px;}
ul.ul_no {list-style-type:none; padding-left:0px; margin-top:0px;}
ul.ul_1 {list-style-type:upper-roman;}
ul.ul_2 {list-style-type:lower-alpha;}
ul.ul_3 {list-style-type:disc;}
div.li_1 {font-weight:bold}
div.li_2 {font-weight:bold}
div.li_3 {font-style:italic}
a {color:black;}
a:hover {color:#0000CC;}
</style>
<
title>Arborescence</title>
</
head>
<
body>
<
div style="width:250px; border:dashed black 1px; padding:2px; float:left;clear:left; position:fixed;">
<
ul class="root">
<!--
/*
Premier bloc : on va parcourir le fichier XSL pour constituer l'index de l'aide
J'utilise un template (une sorte de fonction) nommé index et je lui passe deux paramètres "node" et "level"
"node" est le noeud qui devra être traité par le template
"level" est utilisé pour savoir a quelle profondeur du traitement on se trouve.
Le template "index" est récursif et sera détaillé plus bas.
*/
-->
<
xsl:call-template name="index">
<!--
/*
Pour démarrer, je demande à traiter le topic ayant un parent égal à 0.
J'utilise la syntaxe XPath "//topic[@parent=0]" et mets le résultat dans la variable "node"
*/
-->
<
xsl:with-param name="node" select="//topic[@parent=0]"/>
<
xsl:with-param name="level" select="1"/>
</
xsl:call-template>
</
ul>
</
div>
<
div style="width:600px;height:600px;border:solid black 1px; padding:2px; float:left; margin-left:265px; overflow:auto">
<
ul class="root">
<!--
/*
Deuxième bloc : Même appel avec un template différent car cette fois-ci, je veux parcourir le document pour afficher le contenu et non plus uniquement le sommaire.
Le nouveau Template, "content" est aussi détaillé plus bas
*/
-->
<
xsl:call-template name="content">
<
xsl:with-param name="node" select="//topic[@parent=0]"/>
<
xsl:with-param name="level" select="1"/>
</
xsl:call-template>
</
ul>
</
div>
</
body>
</
html>
</
xsl:template>

<!--
/*
Ceci termine le processing principale du document. On attaque maintenant les Templates appelés plus haut
Ces templates peuvent être définis plus haut ou même dans un document externe qui serait inclu par la fonction xsl:import

Le premier Template se nomme "index" et est appelé avec deux paramètres
"node" et "level"
Les paramètres sont déclarés juste après la définition du template
*/
-->

<
xsl:template name="index">
<
xsl:param name="node" />
<
xsl:param name="level" />
<
li>
<!--
/*
Les paramètres sont utilisés en préfixant leur nom par un $ comme en PHP.
$node est une branche de l'arbre XML. On peut donc utiliser ce paramètr avec toutes les fonctions XPATH et XSL appropriées.
$level est un paramètre statique. On peut s'en servir pour faire des tests, des opérations, etc.

Dans le code ci-dessous, vous noterez parfois l'utilisation des { } pour extraire des valeurs.
Cette syntaxe est utilisée lorsque vous souhaitez récupérer une valeur qui doit etre placée dans un attribut HTML.
Cela remplace l'utilisation du <xsl:value-of select="..." />

Une autre méthode pour définir des attributs HTML est d'utiliser xsl:Attribute.
Par exemple, on aurait pu déclarer le lien ci-dessous de la manière suivante

<a>
<xsl:attribute name="name">
lvl<xsl:value-of select="$node/@parent" />
</xsl:attribute>
<xsl:attribute name="href">
#hlp<xsl:value-of select="$node/@id" />
</xsl:attribute>
<xsl:copy-of select="$node/titre" />
</a>
*/
-->
<
a name="lvl{$node/@parent}" href="#hlp{$node/@id}"><xsl:copy-of select="$node/titre" /></a>
<!--
/*
Le test utilisé ici permet d'éviter de traiter le XML si l'élément de la FAQ n'a pas de dépendance associée.
Pour savoir si mon élément en cours a des topics dépendants, je compte simplement le nombre de topics ayant comme parent l'ID de l'élément en cours.
Le count() est une fonction XPATH
*/
-->
<
xsl:if test="count(//topic[@parent=$node/@id])>0">
<
ul class="ul_{$level}">
<!--
/*
for-each est utilisé pour parcourir une partie du document XML
Ici, je souhaite parcourir tous les "topic" (//topic) dont le parent (@parent) est egale à l'id du noeud que je traite ($node/@id)
Cela me permet de traiter pous les éléments de la FAQ associés au noeud que je traite actuellement
*/
-->

<
xsl:for-each select="//topic[@parent=$node/@id]">
<!--
/*
Le tri par ID est indispensable pour présenter correctement la FAQ.
En effet, le fichier XML ne sera pas spécialement organisé dans l'ordre naturel de la lecture
data-type permet de préciser si on souhaite un tri alphabétique, numérique ou par date.
*/
-->
<
xsl:sort select="@id" order="ascending" data-type="number"/>
<
xsl:call-template name="index">
<!--
/*
Je rappelle ici le template "index" avec comme paramètres du noeud en cours et le "level" incrémenté de 1
*/
-->
<
xsl:with-param name="node" select="."/>
<
xsl:with-param name="level" select="$level+1"/>
</
xsl:call-template>
</
xsl:for-each>
</
ul>
</
xsl:if>
</
li>
</
xsl:template>

<!--
/*
Deuxième template.
Je l'ai séparé du premier pour des facilité de lecture et de compréhension mais il aurait été possible de faire un seul et même template avec un paramètre indiquant si on travaille sur le sommaire ou sur le contenu.
La structure est relativement identique. Seule la mise en forme et le traitement du contenu diffèrent
*/
-->
<
xsl:template name="content">
<
xsl:param name="node" />
<
xsl:param name="level" />
<
li>
<
div style="width:100%;background-color:lightgrey; padding-top:3px; padding-bottom:3px;" class="li_{$level}"><a name="hlp{$node/@id}"/><xsl:value-of select="$node/titre" /></div><br />
<
xsl:if test="$node/data!=''">
<!--
/*
L'utilisation de copy-of a cet endroit permet de ressortir les éventuelles mises en forme HTML.
Si value-of renvoie l'équivalent du texte contenu dans le noeud sélectionné, sans aucune information de tag, copy-of prends tout le noeud et l'intègre sans modification.
Par exemple si on a
<data>Bonjour, <br /> bienvenue sur JeuPHP.</data>
value-of affichera sans ce soucier du <br />
Bonjour, bienvenue sur JeuPHP.
copy-of integrera tous les tags (y compris le <data>)
Bonjour,
bienvenue sur JeuPHP.
*/
-->
<
xsl:copy-of select="$node/data" /><br />
<
br />
</
xsl:if>
<
xsl:if test="count(//topic[@parent=$node/@id])>0">
<
ul class="ul_no">
<
xsl:for-each select="//topic[@parent=$node/@id]">
<
xsl:sort select="id"/>
<
xsl:call-template name="content">
<
xsl:with-param name="node" select="."/>
<
xsl:with-param name="level" select="$level+1"/>

</
xsl:call-template>
</
xsl:for-each>
</
ul>
</
xsl:if>
</
li>
</
xsl:template>
</
xsl:stylesheet>

Avec tout ça, on a une petite aide avec son sommaire

Liens :
Fichier XSL
Fichier XML
Résultat final

(en anglais)
En savoir plus sur le XML
En savoir plus sur le XSL
En savoir plus sur le XPath


RE: Un sommaire et son contenu en XML/XSL - gameprog2 - 13-09-2010

C'est génial ce tutorial !!!
Je vais me mettre aussi à ça alors Wink
Merci pour le tuto, c'est sympa !


RE: Un sommaire et son contenu en XML/XSL - niahoo - 14-09-2010

J'avais utilisé une fonction en php à laquelle on envoyait le fichier xml et le fichier xsl et qui renvoyait le html généré.
(ce qui permettait d'afficher au navigateur du HTML classique, plus facile à parser -- paraît-il -- pour google and Co, mais en perdant la possibilité d'être parsé par une autre application comme la fauille xml de départ).
Je n'arrive plus à la retrouver, je ne trouve que des classes dans la doc PHP or il s'agissait d'une simple fonction, extremement utile.

Donc si vous la connaissez, faites moi signe


RE: Un sommaire et son contenu en XML/XSL - gameprog2 - 14-09-2010

Est ce que ça peut être un truc comme ça ?

http://www.christopher.compagnon.name/sitewww/xsl-genere-xhtml.html


RE: Un sommaire et son contenu en XML/XSL - niahoo - 14-09-2010

il n'est même pas question de php dans ce que tu link. le mot "php" n'y apparaît même pas...


RE: Un sommaire et son contenu en XML/XSL - gameprog2 - 14-09-2010

Ah je croyais que tu voulais sortir du HTML (XHTML) en donnant à une fonction du xml et du xsl ?
c'est le but du lien.
Bon bein si je me suis trompé, excuse !!!
Citation :J'avais utilisé une fonction en php à laquelle on envoyait le fichier xml et le fichier xsl et qui renvoyait le html généré.

C'est sur le site :
Citation :Le seul moyen d'afficher correctement un document avec une belle mise en forme, des couleurs et un confort correct est de générer du HTML ou du XHTML à partir de XML/XSL.



RE: Un sommaire et son contenu en XML/XSL - Roworll - 14-09-2010

Houla.
Bizarre de voir ce sujet rejaillir des entrailles du forum ^^

Pour mettre en forme du XML grâce à XSL via PHP, il faut utiliser le processeur XSLT.
Un exemple simple est visible ici


RE: Un sommaire et son contenu en XML/XSL - niahoo - 14-09-2010

hmmm.. je n'utilisais pas de classe il me semble. J'ai jeté le code, je ne le retrouverai donc pas dans mes fichiers.
(tain tu tas raison je me suis fait avoir par un déterrage)


RE: Un sommaire et son contenu en XML/XSL - Roworll - 14-09-2010

Dans ce cas là, ça doit être relatif à PHP 4 et à la fonction XSLT_Process


RE: Un sommaire et son contenu en XML/XSL - niahoo - 14-09-2010

Peut-être bien, oui.