Miután rájöttem, hogy minden olyan sablon-nyelv használata, amely nyelv nem egyezik meg az éppen használttal, felesleges időfecsérlés, itt volt az ideje, hogy írjak valamit XSLT-vel kapcsolatban. Szóval ha az ember olyan trendi dolgokat használ, mint az MVC, akkor felmerül rá az igény, hogy élete megkönnyítése és a megjelenítő modul megfelelő általánosítása miatt jobb esetben használatba vegyen valami létező sablon-nyelvet, rosszabb esetben írjon egy sajátot. Az XSLT egy kézenfekvő megoldás lehet (mint azt valamikor a régmúltban már kifejtettük), mivel HTML (vagyis inkább XML) szerű, ezért - szerintem - valamivel emberközelibb egy HTML-t ismerő ember számára, mint mondjuk a beágyazott PHP függvények. Emellett, ha a dolgot PHP oldalról közelítjük meg, az XSLT feldolgozására egy egész kiterjesztés áll (vagy éppen nem áll) rendelkezésünkre, minek segítségével pár sorban el tudjuk intézni az oldal generálását.
A dolog esetünkben úgy néz ki, hogy létezik egy template.xml és egy template.xsl. A template.xml-ben találhatóak az alapértelmezett adatok (vagy csak az alapértelmezett adatszerkezet üresen), a template.xsl pedig maga a sablon, amire ráhúzzuk a template.xml segítségével az adatokat. Ennek a megoldásnak az előnye, hogy így az adatokat egyszerűen XPath segítségével (ami szintén beépített támogatást élvez PHP-ben) pofonegyszerűen tudjuk majd átadni az XSLT feldolgozónak. Nézzük a példafájlokat:
template.xml <?xml version="1.0" encoding="utf-8"?> <content> <title value=""/> <url value=""/> <content><![CDATA[]]></content> </content>
template.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="no"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="hu">
<head>
<title><xsl:value-of select="content/title/@value"/></title>
</head>
<body>
<h1><a href="{content/url/@value}"><xsl:value-of select="content/title/@value"/></a></h1>
<p><xsl:value-of select="content/text" disable-output-escaping="yes"/></p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Igazából innentől már csak egy minimális PHP kód következik, ami előre definiált adatok alapján (a $transformation tömb, amit a feldolgozó modul elég sok módon megkaphat) feltölti a betöltött template.xml-t adatokkal és a template.xsl segítségével elkészíti a kívánt formátumot:
/*
'Tartalom' betöltése
*/
$content_xsl = &DOMDocument::load('template.xsl');
$content = &DOMDocument::load('template.xml');
$content_xpath = &new DOMXPath($content);
$transformation['/content/title/@value'] = 'Valami cím';
$transformation['/content/url/@value'] = 'http://www.something.com/';
$transformation['/content/content/text()'] = 'Valami szöveg...';
/*
Transzformációk végrehajtása
*/
foreach ($transformation as $path => $value) {
if (!is_array($value)) {
$content_xpath->query($path)->item(0)->nodeValue = $value;
}
else {
foreach ($value as $key => $node) {
$content_node = $content->importNode($node, true);
$content_xpath->query($path)->item(0)->appendChild($content_node);
}
}
}
$proc = &new XSLTProcessor();
$proc->importStylesheet($content_xsl);
print $proc->transformToDoc($content)->saveXML();
A lényeg a $transformation tömb megadása, ami a feljebb betöltött XML fájlt alakítja át. Ahogy az a foreach ciklusban látszik, két fajta értéket adhatunk az XPath szerű asszociatív hozzárendelésnek. Sima stringet, vagy egy tömböt. Tömb esetén a tömbelemek értékei DOMDocument típusúak kell, hogy legyenek.
A dolog legnagyobb szépsége viszont az, hogy ha a template.xsl-t lecseréljük, de minden mást változatlanul hagyunk, akkor például HTML helyett generálhatunk akár RSS-t is:
template.xsl <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="utf-8" indent="no"/> <xsl:template match="/"> <rss version="2.0"> <channel> <title>Teszt RSS</title> <link>http://www.something.com/</link> <description>Ez egy teszt fájl a teszt RSS-nek...</description> <item> <title><xsl:value-of select="content/title/@value"/></title> <link><xsl:value-of select="content/url/@value"/></link> <description><xsl:value-of select="content/content/text()"/></description> </item> </channel> </rss> </xsl:template> </xsl:stylesheet>
De szép az élet így, ha van valami, ami eléggé megkönnyíti (persze a header-rel még egy csepp gond van így ebben az esetben, de az most lényegtelen). Nosza, lehet nekiállni a régi és megunt rendszeredet XSLT alapokra helyezni, mert az - ahogy a fenti példa is mutatja - jó. De természetesen ízlés kérdése. Ha az ember csak egy saját kis oldalt fejlesztget, és tudja, hogy más nem fog belenyúlni a sablonokba, akkor igazából a PHP, mint sablon-nyelv is tökéletesen megfelel a célra. Tehát: használja, aki úgy érzi, hogy szüksége van rá.
Ezt az írást követte el 06:37-kor. Kommentelj! 

Szia!
Hát én 4 év delay-el, de ugyanarra jutottam egy egész kemény saját Template engine kifejlesztése után., mint te. Nevezetesen, hogy XML+XSL párossal sokkal jobban meg lehet oldani a megjelenítést, mint bármilyen template rendszerrel. Kevesen jutnak el idáig szerintem. :-)
Most éppen azon tökölök, hogy saját rendszert dolgozzak ki erre a célra. Gondolom te is észrevetted, hogy egy TextInput-nál ugyanazt az XML részletet bekérheted, mint amit a kiírásnál XSL-el XHTML-re alakítasz? A validálás és jogok adása ezzel a módszerrel pofonegyszerű. Másrészt meg ha cacheli a böngésző az XSL fájlokat, akkor szerintem az adatforgalom is kisebb lesz, mintha sima HTML-t küldenél át.
Kíváncsi lennék, hogy így 4 év után neked mik a tapasztalataid a témában?
Közben eszembe jutott, hogy php osztályok generáltatására is simán lehetne használni mindezt...
pl én éppen fejlesztek egy ORM rendszert, aminél ilyen XML-ben tárolom le az adatokat:
<?xml version="1.0" encoding="utf-8" ?>
<model
xmlns:package="mapping.package"
xmlns:class="mapping.class"
xmlns:integer="mapping.datatype.integer"
xmlns:string="mapping.datatype.string"
xmlns:one="mapping.relationship.one"
xmlns:many="mapping.relationship.many"
>
<package:testdb location="localhost:1234" user="root" password="test" charset="utf-8">
<class:user>
<integer:id size="3" />
<string:name size="128" />
<string:email size="128" />
</class:user>
<class:book>
<integer:id size="6" />
<string:name size="128" />
</class:book>
<class:relationship>
<one:user />
<many:book />
</class:relationship>
</package:testdb>
</model>
Egy jól megírt XSL fájllal ebből simán lehetne osztályokat generáltatni parser nélkül. :-) Egyre jobban tetszik ez a megközelítés :):):)
Végül nem merültem bele annyira a dologba és jutottam el odáig, hogy élesben is használjak XSL alapú sablonrendszert. Leragadtam a szerintem átláthatóbb és kényelmesebben gépelhető Smarty-szerű sablonnyelveknél (mint ami például a Szükségesek-e a sablonnyelvek? végén említve is lett).
Pár éve még volt egy kis próbálkozás a kliens oldali felhasználást tekintve, de azt se használtam még éles környezetben. Mindenesetre a kliens oldali elgondolás nekem jobban tetszik, főleg ha valami olyan oldalról van szó, ami esetleg más oldalaknak szolgáltat adatokat, mert akkor a weboldal maga lehet akár egyben az API is.