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á.

++++-

Hozzászólások Hozzászólások RSS

  1. 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?

    inf3rnoApril 5, 2010
  2. 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 :):):)

    inf3rnoApril 5, 2010
  3. 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.

Szólj hozzá!

regisztráció, bejelentkezés

Az oldalon nem jelenik meg.

Ezeket a tageket használhatod: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>