Syntaxe

les fichiers templates sont des fichiers xml avec plusieurs namespace, pour le moment, le moteur de template s'appelle starfish template. l'espace de nom spécifique au template est sft, il est déclaré comme ceci : xmlns:sft="http://sft/". Dans l'exemple plus bas, la déclaration est faite sur la balise html, pour le moment, la déclaration renvoie sur une url bidon.

exemple d'une portion de template :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:sft="http://sft/">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	</head>

	<body>
	<table border="1">
		<sft:block function="processtr">
		<tr>
			<sft:block function="processtd">
			<td>
				<sft:value />
			</td>
			</sft:block>
		</tr>
		</sft:block>
	</table>
	</body>
</html>

le php correspondant au template :

<?php

class stats {
	private static $_instance;
	private $sft;
	private $display;
	private $currentrow;
	private $currentvalue;

	private function __construct() {

		$this->display = array();
		
		$rows = range(0, 10);
		foreach($rows as $row) {
			$this->display[$row] = range(0, 10);
		}

		$obj->sft = xhtmltemplate::getInstance();
		$obj->sft->processFile(__CLASS__, 'sft.xml');
		$obj->sft->echoXhtml();
	}

	private static function getInstance() {
		if (!isset(self::$_instance)) 
			self::$_instance = new self();
		return self::$_instance;
	}


	public static function processtr($node) {
		$obj = self::getInstance();
		while (list(,$obj->currentrow) = each($obj->display)) {
			$obj->sft->cloneChildNodes($node);
			}
	}

	public static function processtd($node) {
		$obj = self::getInstance();
		while (list(,$obj->currentvalue) = each($obj->currentrow)) {
			$obj->sft->cloneChildNodes($node);
			}
	}

	public static function onProcessTag($node) {
		$obj = self::getInstance();
		$obj->sft->setNodeText($node, $obj->currentvalue);
	}
}
?>

Il y a deux cas possible pour les balises préfixées avec sft:, si la balise à des enfants, c'est un bloc, si il n'y a pas d'enfants, c'est une variable. Dans le php, c'est la classe xhtmltemplate qui fournie les outils de traitement du template. La fonction processFile( effectue le traitement du template, a chaque fois qu'un tag du namespace sft est rencontré dans le fichier, une fonction est appelée dans la classe.

Par défaut, les blocs appellent la fonction onProcessBloc et les variables appellent onProcessTag mais les noms des fonction peuvent être remplacés avec l'attribut function dans le template (comme dans l'exemple avec processtd et processtr)

La fonction echoXhtml convertis l'objet DOMDocument en chaîne de caractères puis affiche le résultat. Le traitement du template à supprimé touts les nœuds du namespace sft, à l'affichage il ne restera que le xhtml.

Avantages de l'xml

Le remplacement des variables se fait grâce aux fonctions du DOM, ce qui évite d'avoir à s'occuper des caractères spéciaux. Les éventuelles erreur dans le template sont signalée aussitôt car le DOM n'accepte que le xml pur. De plus, il est possible de valider le résultat avec la fonction DOMDocument->validate().
La Conversion en chaîne de caractères s'effectue au dernier moment, il est toujours possible de revenir sur du html déja traité, au niveau du développement, cela permet de créer des fonctions dans le template qui vont ajouter des feuilles de styles dans le <head></head> du document html par exemple.

Problèmes de performances

Le fait de traiter des boucles importantes dans les templates pénalise au niveau des performance par rapport aux templates traditionnels. Je pense que cela est due en partie à la fonction DOMNode->cloneNode().

Sur ce graphique, la partie traitement du DOM comparée à la conversion en chaîne de caractères pour l'affichage

Sur ce graphique, sft comparé à smarty

Sur les 2 graphiques, le template rempli un tableau de 2x2 à 44x44 cases, en ordonnées, le temps en secondes.
Je n'ai pas encore trouvé de moyen efficace pour le clonage des nœuds s'effectue plus rapidement.

Ce moteur de template n'est qu'une partie d'un projet plus important, j'espere pouvoir en dire plus bientôt quand le code sera plus avancé. Pour les développeurs interessés, une version en cours de développement est disponible ici (ce n'est pas la peine de me poser des question sur cette version elle est forcement pleine de bugs)