<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>deadlime.project &#187; sablonok</title>
	<atom:link href="http://deadlime.hu/tag/sablonok/feed/" rel="self" type="application/rss+xml" />
	<link>http://deadlime.hu</link>
	<description>squeezed out</description>
	<lastBuildDate>Tue, 24 Jan 2012 21:54:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Szükségesek-e a sablonnyelvek?</title>
		<link>http://deadlime.hu/2007/10/14/szuksegesek-e-a-sablonnyelvek/</link>
		<comments>http://deadlime.hu/2007/10/14/szuksegesek-e-a-sablonnyelvek/#comments</comments>
		<pubDate>Sun, 14 Oct 2007 12:41:09 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[sablonok]]></category>
		<category><![CDATA[Smarty]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2007/10/14/szuksegesek-e-a-sablonnyelvek/</guid>
		<description><![CDATA[Régebben írtam a PHP sablonnyelvként való használatáról. Lehet szépíteni a dolgokat, de hosszú távon ennek a használata (főleg megfelelő szerkesztőprogrambeli makrók nélkül) kényelmetlen, hosszadalmas és még a makrók használatával együtt is csúnya, olvashatatlan. A Smarty egyetlen pozitívuma az, hogy egyszerűen és gyorsan lehet írni, kényelmesen lehet használni. Persze ez nem vigasz azoknak, akik nem akarnak [...]]]></description>
			<content:encoded><![CDATA[<p>Régebben írtam a PHP sablonnyelvként való használatáról. Lehet szépíteni a dolgokat, de hosszú távon ennek a használata (főleg megfelelő szerkesztőprogrambeli makrók nélkül) kényelmetlen, hosszadalmas és még a makrók használatával együtt is csúnya, olvashatatlan. A Smarty egyetlen pozitívuma az, hogy egyszerűen és gyorsan lehet írni, kényelmesen lehet használni. Persze ez nem vigasz azoknak, akik nem akarnak egy több ezer kódsorból álló sablon kezelőt használni csak emiatt a kényelem miatt.</p>

<p>Nagyrészt így vagyok vele én is. Gyakorlatilag a szintaktikájának az alapjait leszámítva nem lenne szükségem semmire a Smarty-ból. Nem érdekel, hogy korlátozni lehet a sablon íróját, hogy a PHP eszköztár csak egy részét használhassa (minek is korlátoznám magam...). Nem érdekel, hogy könnyen és gyorsan lehet hozzá plugineket írni (ha az egész PHP használható lenne, erre nincs is túl nagy szükség). Nincs szükségem semmi ilyesmire.<br/>
Sokkal inkább vonz az, ha a nyelvet gyorsan lehet gépelni (pl. mert rövid, minimális speciális karaktert használ és logikus a szerkezete). Az se egy hátrány, ha az elkészült sablon valamilyen szinten olvasható lesz. Nem lenne rossz még, ha egy elfogadható minőségű PHP kódot generálna az én sablonomból, ami aztán elfogadható (a lehető leggyorsabb) sebességgel futna. Az első kettőt még csak-csak teljesíti, de az utolsóval eléggé hadilábon áll a Smarty. Így itt az idő valami más után nézni...</p><span id="more-108"></span>

<p>A legkézenfekvőbb dolog a PHP használata lenne erre a célra, ami az első két ponton totálisan megbukik. Kiindulási alapnak viszont jó lesz:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;Valami sablon&lt;/h1&gt;

&lt;?php if (5 &gt; 6): ?&gt;
	&lt;p&gt;&lt;?php print('5 nagyobb mint 6'); ?&gt;&lt;/p&gt;
&lt;?php else: ?&gt;
	&lt;p&gt;&lt;?php print('5 nem nagyobb, mint 6'); ?&gt;&lt;/p&gt;
&lt;?php endif; ?&gt;</pre>

<p>Mi lenne, ha első körbe a <code>&lt;?php</code> és a <code>?&gt;</code> helyett a jól megszokott <code>{</code> és <code>}</code> lenne használva?</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;Valami sablon&lt;/h1&gt;

{ if (5 &gt; 6): }
	&lt;p&gt;{ print('5 nagyobb mint 6'); }&lt;/p&gt;
{ else: }
	&lt;p&gt;{ print('5 nem nagyobb, mint 6'); }&lt;/p&gt;
{ endif; }</pre>

<p>Haladunk, esetleg még a <code>print()</code> helyett bevezethetnénk a PHP rövid tag <code>&lt;?=</code> szerkezetéhez hasonlóan egy <code>{=</code> szerkezetet:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;Valami sablon&lt;/h1&gt;

{ if (5 &gt; 6): }
	&lt;p&gt;{= '5 nagyobb mint 6' }&lt;/p&gt;
{ else: }
	&lt;p&gt;{= '5 nem nagyobb, mint 6' }&lt;/p&gt;
{ endif; }</pre>

<p>Pár kényelmességet elősegítő lépés múlva (szóközök, kettőspontok, felesleges zárójelek, pontosvesszők eltűntetése) sikerült eljutnom a végleges formáig:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;Valami sablon&lt;/h1&gt;

{if 5 &gt; 6}
	&lt;p&gt;{='5 nagyobb mint 6'}&lt;/p&gt;
{else}
	&lt;p&gt;{='5 nem nagyobb, mint 6'}&lt;/p&gt;
{if}</pre>

<p>Rémisztően hasonlít a Smarty-ra (ez valamilyen szinten cél is volt :)), viszont az ebből fordított PHP kód gyakorlatilag egy az egyben megegyezik az általunk írt sablon kód szerkezetével. Most, hogy megvan az alapvető szintaxis, jöhet a sablonkezelő osztály, ami a fentebb említett több ezer sorhoz képest megvalósult úgy 170 sorból (milyen csodákra képes, ha kihagyunk minden "szemetet", amire nincs szükségünk :)), ami már tartalmaz pár extra funkciót is (mint például a lefordított sablonok újrafordítási szükségességének ellenőrzését). A bemenete egy <a href="http://kriz.deadlime.hu/lighty/template.html" target="_blank">ilyen template</a>, amiből ezt a <a href="http://kriz.deadlime.hu/lighty/template.phps" target="_blank">PHP kódot</a> generálja, valami ilyesmi kóddal:</p>

<pre class="code prettyprint lang-php">&lt;?php
	include('lighty.php');
	
	$l = new Lighty();
	
	$l-&gt;assign('list', array('a', 'b', 'c', 'd'));
	$l-&gt;display('teszt.tpl');
?&gt;</pre>

<p>Amit érdemes ezzel kapcsolatban megemlíteni, hogy a lefordított forrás első sorának elején ott van egy kommentben a fordítás ideje, ami az újrafordítás-ellenőrző számára fontos. Valamint az egész fájl egyetlen egy PHP kódblokkot tartalmaz (ami emlékeim szerint optimálisabb, mint sok-sok kis PHP kódblokk egy sablonon belül). Emiatt vannak felesleges, csak whitespace karaktereket kiíró <code>print()</code> hívások, de ezek megszüntethetőek. És végül, de nem utolsó sorban, a Lighty névre keresztelt sablonrendszer első publikus verziója <a href="http://kriz.deadlime.hu/lighty/lighty.zip">letölthető innen</a>. A csomagban megtalálható egy teszt.php is, ami a fentebb felvázolt példakódot tartalmazza, valamint az általa használt template fájlok és szükséges könyvtárak is.</p>

<p>És hogy így a végén még a címben említett kérdést is megválaszoljam: szerintem szükség van a sablonnyelvekre, mert nagyban meg tudják könnyíteni az ember életét az által, hogy meggyorsítják a sablonírás folyamatát.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2007/10/14/szuksegesek-e-a-sablonnyelvek/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>PHP, mint sablonnyelv</title>
		<link>http://deadlime.hu/2006/07/28/php-mint-sablonnyelv/</link>
		<comments>http://deadlime.hu/2006/07/28/php-mint-sablonnyelv/#comments</comments>
		<pubDate>Fri, 28 Jul 2006 08:47:24 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[sablonok]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/07/28/php-mint-sablonnyelv/</guid>
		<description><![CDATA[A weblaboron blogmarkként megjelent írás nagyrészt egyezik az álláspontommal a sablonkezelő rendszerek, sablonnyelvek terén, ezért ebbe nem is akarok nagyobb mélységekbe belemenni. Az utóbbi időben volt alkalmam huzamosabb ideig használni a Smarty-t és tényleg egy jó kis nyelvnek bizonyult arra, hogy az ember sablonokat gyártson, és azok a sablonok átláthatóak is legyenek (amennyire legalábbis egy [...]]]></description>
			<content:encoded><![CDATA[<p>A weblaboron blogmarkként megjelent <a href="http://www.phppatterns.com/docs/design/templates_and_template_engines">írás</a> nagyrészt egyezik az álláspontommal a sablonkezelő rendszerek, sablonnyelvek terén, ezért ebbe nem is akarok nagyobb mélységekbe belemenni. Az utóbbi időben volt alkalmam huzamosabb ideig használni a Smarty-t és tényleg egy jó kis nyelvnek bizonyult arra, hogy az ember sablonokat gyártson, és azok a sablonok átláthatóak is legyenek (amennyire legalábbis egy másik nyelv+HTML átlátható maradhat). Viszont ha csak a deadlime.project alatt dübörgő WordPress-t vesszük, abban viszont a PHP veszi át ezt a szerepet is.</p>

<p>Vannak esetek, amikor egy külön sablonnyelv célravezetőbb lehet, a sablont írók lekorlátozása, az átláthatóság vagy egyéb okok folytán. De milyen eszközök állnak a rendelkezésünkre, ha a PHP-t szeretnénk használni erre a feladatra? A dolgot rendkívül egyszerűen is elintézhetjük, és írhatunk ehhez hasonló sablonokat is:</p><span id="more-69"></span>

<pre class="code prettyprint lang-php">&lt;?php
	echo &quot;&lt;h1&gt;&quot;.$data['title'].&quot;&lt;/h1&gt;
		&lt;p&gt;&quot;.$data['text'].&quot;&lt;/p&gt;&quot;;
?&gt;</pre>

<p>Azon kívül, hogy az így kapott sablonok baromi rondák és átláthatatlanok (főleg ha már elágazásokkal és ciklusokkal is tele vannak tűzdelve), böngészőben sem tudjuk rögtön megnézni őket. Nézzük tehát az első módosítást, amit eszközölhetünk a kódon:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;&lt;?php echo $data['title']; ?&gt;&lt;/h1&gt;
&lt;p&gt;&lt;?php echo $data['text']; ?&gt;&lt;/p&gt;</pre>

<p>Így már böngészőben is meg tudjuk nézni a készülő sablont, viszont nem lett sokkal szebb és átláthatóbb. Ha engedélyezve vana  php.ini-ben a <code>short_open_tag</code> direktíva, akkor van lehetőségünk használni a következő formát:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;&lt;?=$data['title'] ?&gt;&lt;/h1&gt;
&lt;p&gt;&lt;?=$data['text'] ?&gt;&lt;/p&gt;</pre>

<p>Amennyiben erre nincs lehetőségünk, érdemes bevezetni egy függvényt, ami az adott indexű tagot elküldi a kimenetre. Legyen egy ilyen <code>data($key, $return=false)</code> függvény, ami <code>$return=true</code> esetén nem a kimenetre küldi az adatot hanem visszaadja. Ez esetben így módosul a kód:</p>

<pre class="code prettyprint lang-php">&lt;h1&gt;&lt;?php data('title'); ?&gt;&lt;/h1&gt;
&lt;p&gt;&lt;?php data('text'); ?&gt;&lt;/p&gt;</pre>

<p>A következő dolog a vezérlési szerkezetek. Az ember hamar bele tud bonyolódni a sablon végén gyülekező <code>&lt;?php } ?&gt;</code> stringekbe, hogy az akkor most melyik if vagy éppen while végét jelzi. Ilyen esetekben egész jól használhatók a PHP alternatív vezérlési szerkezetei, melyek annyiban térnek el a jól megszokott szintaxistól, hogy a soruk végén nem nyitó kapcsos zárójel van, hanem kettőspont és nem záró kapcsos zárójellel végződnek hanem a nevüknek megfelelő <code>endif;</code>, <code>endwhile;</code>, <code>endfor;</code>, <code>endforeach;</code>, vagy <code>endswitch;</code> szavakkal. Nézzünk példát is:</p>

<pre class="code prettyprint lang-php">&lt;? while ($post = data('post_object', true)-&gt;get_next_post()): ?&gt;
&lt;div class=&quot;post&quot; id=&quot;post-&lt;?=$post['id'] ?&gt;&quot;&gt;
	&lt;? if ($post['id'] === 1): ?&gt;
		&lt;h1&gt;&lt;?=$post['title'] ?&gt;&lt;/h1&gt;
	&lt;? else: ?&gt;
		&lt;h2&gt;&lt;?=$post['title'] ?&gt;&lt;/h2&gt;
	&lt;? endif; ?&gt;
	&lt;div class=&quot;post-text&quot;&gt;&lt;?=$post['text'] ?&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;? endwhile; ?&gt;</pre>

<p>Persze a while-ban használt szerkezet csak PHP 5-ben működőképes, legalábbis az általam legutóbb használt PHP 4-es verzió még nem szerette, ha egy függvény által visszaadott objektumra ilyen módon hivatkozok. Nézzük meg, hogy egy hasonló dolgora használt kód hogyan nézne ki Smarty-ban:</p>

<pre class="code prettyprint lang-xml">{section name=&quot;post&quot; loop=$posts}
&lt;div class=&quot;post&quot; id=&quot;post-{$posts[post].id}&quot;&gt;
	{if $posts[post].id == 1}
		&lt;h1&gt;{$posts[post].title}&lt;/h1&gt;
	{else}
		&lt;h2&gt;{$posts[post].title}&lt;/h2&gt;
	{/if}
	&lt;div class=&quot;post-text&quot;&gt;{$posts[post].text}&lt;/div&gt;
&lt;/div&gt;
{/section}</pre>

<p>Tény, hogy ez azért egy sokkal átláthatóbb sablonkód (és ha még azt is számításba vesszük, hogy a PHP-nél a legjobb esetet vettem figyelembe, mivel az olvashatóságot még ronthatná a teljes &lt;?php nyitótag és a &lt;?= helyett az echo-s változat), viszont arról sem szabad megfeledkezni, hogy ez is csak egy alternatíva, mondjuk egy olyan alternatíva, amikor a sablonkódot csak mi, vagy csak olyan emberek írják, akik értenek a PHP-hez. Nézzünk még a végére egy kis WordPress template kódot is, ami hasonló célt szolgál mint a fenti két kód:</p>

<pre class="code prettyprint lang-php">&lt;div class=&quot;post&quot; id=&quot;post-&lt;? the_ID(); ?&gt;&quot;&gt;
	&lt;? if ($post-&gt;ID === 1): ?&gt;
		&lt;h1&gt;&lt;? the_title(); ?&gt;&lt;/h1&gt;
	&lt;? else: ?&gt;
		&lt;h2&gt;&lt;? the_title(); ?&gt;&lt;/h2&gt;
	&lt;? endif; ?&gt;
	&lt;div class=&quot;post-text&quot;&gt;&lt;? the_content('Tovább...'); ?&gt;&lt;/div&gt;
&lt;/div&gt;</pre>

<p>Mint az látszik, olyan projektekben is használható a PHP alapú sablonnyelv-rendszer, mint a <a href="http://wordpress.org/">WordPress</a>, amit nem hiszem, hogy csak (PHP) programozók használnának és nem hiszem, hogy csak ők írnának rá sablonokat, vagy piszkálnának bele a már meglévő sablonjaikba. Vagy egy másik jó példa a <a href="http://drupal.org/">Drupal</a> lehetne, ami szintén egy elég menő tartalomkezelő rendszer (bár ott, amennyire tudom több féle megoldás is létezik a template írására). Lényeg, hogy egyik módszert sem akarom lehordani, csak néha érdemes elgondolkozni, hogy az éppen aktuális munka készítése során mikor szükséges külön eszközt használni arra, amit a PHP-vel is könnyen megoldhatunk.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/07/28/php-mint-sablonnyelv/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Objektum-orientált C++ V.</title>
		<link>http://deadlime.hu/2006/04/05/objektum-orientalt-cpp-5/</link>
		<comments>http://deadlime.hu/2006/04/05/objektum-orientalt-cpp-5/#comments</comments>
		<pubDate>Wed, 05 Apr 2006 22:20:02 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[objektum-orientált]]></category>
		<category><![CDATA[sablonok]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/04/05/objektum-orientalt-cpp-5/</guid>
		<description><![CDATA[Annak idején ott hagytuk abba, hogy elkészítettünk egy új adatszerkezetet, ami nem más volt mit a láncolt lista. Elkészítettünk hozzá egy használható felhasználói felületet, aztán elkezdhetünk gondolkozni azon, hogy mi van, ha mi nem egyszerű inteket akarunk abban a listában tárolni, hanem valami teljesen mást? Mert hát miért is akarnánk az inteknél leragadni, amikor annyi [...]]]></description>
			<content:encoded><![CDATA[<p>Annak idején ott hagytuk abba, hogy elkészítettünk egy új adatszerkezetet, ami nem más volt mit a láncolt lista. Elkészítettünk hozzá egy használható felhasználói felületet, aztán elkezdhetünk gondolkozni azon, hogy mi van, ha mi nem egyszerű <code>int</code>eket akarunk abban a listában tárolni, hanem valami teljesen mást? Mert hát miért is akarnánk az <code>int</code>eknél leragadni, amikor annyi minden van még.</p>

<p>Ilyen megközelítésben természetesen eléggé használhatatlannak bizonyul a kódunk, mert csak arra az egy típusra működik megfelelően. Még szerencse, hogy itt vannak a sablonok, amikkel ez a probléma relatíve egyszerűen áthidalható.</p><span id="more-29"></span>

<p>Bevezetésnek kezdjünk valami egyszerű függvénnyel, mondjuk amivel össze tudunk adni mindenféle objektumot, aminek meg van adva a <code>+</code> operátora (tény, hogy a példa cseppet értelmetlen, de mondjuk gondoljunk akkor egy <code>sort()</code> függvényre, aminek végülis mindegy, hogy milyen adatokat hasonlít össze, amíg annak az adatszerkezetnek megvan a <code>&lt;</code> vagy <code>&gt;</code> operátora).</p>

<pre class="code prettyprint lang-c">#include &lt;string&gt;
#include &lt;iostream&gt;

template&lt;class T&gt; T Add(const T&amp; o1, const T&amp; o2)
{
    return o1 + o2;
}

int main()
{
    int i1 = 1;
    int i2 = 2;
    int i3 = Add(i1, i2);
    std::cout &lt;&lt; i3 &lt;&lt; std::endl;

    std::string s1 = &quot;abc&quot;;
    std::string s2 = &quot;xyz&quot;;
    std::string s3 = Add(s1, s2);
    std::cout &lt;&lt; s3 &lt;&lt; std::endl;
}</pre>

<p>Ennyi az egész, tulajdonképpen csak a választott függvényünk elé tesszük, hogy <code>template&lt;class T&gt;</code> és mindenhol, ahol egyébként mondjuk int-et írtunk volna, ott T-t használunk. Hasonló a helyzet az osztályok esetében is, nézzük először a már megírt cList.h fájlunk sablonosított változatát.</p>

<pre class="code prettyprint lang-c">#ifndef __CLIST_H__
#define __CLIST_H__

template&lt;class T&gt; struct listNode
{
    listNode&lt;T&gt; *prev;
    listNode&lt;T&gt; *next;
    T data;

    listNode()
    {
        next = prev = this;
    }
    listNode(const T&amp; num)
    {
        next = prev = this;
        data = num;
    }
};

template&lt;class T&gt; class cList
{
    private:
        listNode&lt;T&gt;* list;

        void Create(void);
        void Destroy(void);

        void Remove(listNode&lt;T&gt;* target);
        listNode&lt;T&gt;* Get(listNode&lt;T&gt;* target);
    public:
        cList(void);
        cList(const cList&lt;T&gt; &amp;other);
        ~cList(void);

        class E_OUTOFMEMORY {};
        class E_INVALIDITEM {};

        void left_insert(listNode&lt;T&gt;* target, listNode&lt;T&gt;* data);
        void right_insert(listNode&lt;T&gt;* target, listNode&lt;T&gt;* data);
        listNode&lt;T&gt;* get_first(void);
        listNode&lt;T&gt;* get_last(void);
        listNode&lt;T&gt;* Search(const T&amp; number);

        cList&lt;T&gt;&amp; operator+(const cList&lt;T&gt;&amp; other);
        cList&lt;T&gt;&amp; operator=(const cList&lt;T&gt;&amp; other);
        cList&lt;T&gt;&amp; operator&gt;&gt;(T&amp; number);
        cList&lt;T&gt;&amp; operator&gt;&gt;(listNode&lt;T&gt;* pointer);
        cList&lt;T&gt;&amp; operator&lt;&lt;(const T&amp; number);
        cList&lt;T&gt;&amp; operator&lt;&lt;(listNode&lt;T&gt;* pointer);
};</pre>

<p>Pár <code>&lt;T&gt;</code>-től talán még megszabadulhatnánk, ha a <code>listNode</code> osztályt a <code>cList</code> osztályon belül adnánk meg, de most már mindegy (egy kis gyakorlás gyanánt mindenki megcsinálhatja magának). Most, hogy volt egy kis szünet, mindenki kifújta magát, visszatérhetünk az osztály metódusainak kibontogatására (maradunk a cList.h-ban):</p>

<pre class="code prettyprint lang-c">template&lt;class T&gt; void cList&lt;T&gt;::Create(void)
{
    list = new listNode&lt;T&gt;();
    if (!list) throw E_OUTOFMEMORY();
 
    list-&gt;next = list;
    list-&gt;prev = list;
    return;
}

template&lt;class T&gt; void cList&lt;T&gt;::Destroy(void)
{
    while (list-&gt;prev != list) {
        Remove(list-&gt;prev);
    }
    return;
}

template&lt;class T&gt; void cList&lt;T&gt;::Remove(listNode&lt;T&gt;* target)
{
    listNode&lt;T&gt;* tmp = Get(target);
    delete tmp;
    return;
}

template&lt;class T&gt; listNode&lt;T&gt;* cList&lt;T&gt;::Get(listNode&lt;T&gt;* target)
{
    target-&gt;prev-&gt;next = target-&gt;next;
    target-&gt;next-&gt;prev = target-&gt;prev;
    target-&gt;prev = target;
    target-&gt;next = target;
    return target;
}

template&lt;class T&gt; cList&lt;T&gt;::cList(void)
{
    Create();
}

template&lt;class T&gt; cList&lt;T&gt;::cList(const cList&lt;T&gt;&amp; other)
{
    Create();
 
    listNode&lt;T&gt;* tmp = other.list-&gt;next;
    while (tmp != other.list) {
        listNode&lt;T&gt;* node = new listNode&lt;T&gt;(tmp-&gt;data);
        if (!node) throw E_OUTOFMEMORY();
 
        this-&gt;left_insert(this-&gt;list, node);
        tmp = tmp-&gt;next;
    }
}

template&lt;class T&gt; cList&lt;T&gt;::~cList(void)
{
    Destroy();
    delete list;
}

template&lt;class T&gt; void cList&lt;T&gt;::left_insert(listNode&lt;T&gt;* target, listNode&lt;T&gt;* data)
{
    data-&gt;prev = target-&gt;prev;
    data-&gt;next = target;
    target-&gt;prev-&gt;next = data;
    target-&gt;prev = data;
    return;
}
template&lt;class T&gt; void cList&lt;T&gt;::right_insert(listNode&lt;T&gt;* target, listNode&lt;T&gt;* data)
{
    data-&gt;prev = target;
    data-&gt;next = target-&gt;next;
    target-&gt;next-&gt;prev = data;
    target-&gt;next = data;
    return;
}

template&lt;class T&gt; listNode&lt;T&gt;* cList&lt;T&gt;::get_first(void)
{
    if (list-&gt;next == list) throw E_INVALIDITEM();
    return Get(list-&gt;next);
}
template&lt;class T&gt; listNode&lt;T&gt;* cList&lt;T&gt;::get_last(void)
{
    if (list-&gt;prev == list) throw E_INVALIDITEM();
    return Get(list-&gt;prev);
}

template&lt;class T&gt; listNode&lt;T&gt;* cList&lt;T&gt;::Search(const T&amp; number)
{
    listNode&lt;T&gt;* tmp = list-&gt;next;
    while (number != tmp-&gt;data &amp;&amp; tmp != list) {
        tmp = tmp-&gt;next;
    }
    if (tmp == list) throw E_INVALIDITEM();
    return tmp;
}

template&lt;class T&gt; cList&lt;T&gt;&amp; cList&lt;T&gt;::operator+(const cList&lt;T&gt;&amp; other)
{
    listNode&lt;T&gt;* tmp = other.list-&gt;next;
    while (tmp != other.list) {
        listNode&lt;T&gt;* node = new listNode&lt;T&gt;(tmp-&gt;data);
        if (!node) throw E_OUTOFMEMORY();
 
        this-&gt;left_insert(this-&gt;list, node);
        tmp = tmp-&gt;next;
    }
}
template&lt;class T&gt; cList&lt;T&gt;&amp; cList&lt;T&gt;::operator=(const cList&lt;T&gt;&amp; other)
{
    if (this == &amp;other) return *this;
    this-&gt;Destroy();
 
    listNode&lt;T&gt;* tmp = other.list-&gt;next;
    while (tmp != other.list) {
        listNode&lt;T&gt;* node = new listNode&lt;T&gt;(tmp-&gt;data);
        if (!node) throw E_OUTOFMEMORY();
 
        this-&gt;left_insert(this-&gt;list, node);
        tmp = tmp-&gt;next;
    }
    return *this;
}

template&lt;class T&gt; cList&lt;T&gt;&amp; cList&lt;T&gt;::operator&gt;&gt;(T&amp; number)
{
    number = get_last()-&gt;data;
    return *this;
}
template&lt;class T&gt; cList&lt;T&gt;&amp; cList&lt;T&gt;::operator&gt;&gt;(listNode&lt;T&gt;* pointer)
{
    pointer = get_last();
    return *this;
}
 
template&lt;class T&gt; cList&lt;T&gt;&amp; cList&lt;T&gt;::operator&lt;&lt;(const T&amp; number)
{
    listNode&lt;T&gt;* tmp = new listNode&lt;T&gt;(number);
    if (!tmp) throw E_OUTOFMEMORY();
 
    left_insert(list, tmp);
    return *this;
}
template&lt;class T&gt; cList&lt;T&gt;&amp; cList&lt;T&gt;::operator&lt;&lt;(listNode&lt;T&gt;* pointer)
{
    left_insert(list, pointer);
    return *this;
}

#endif</pre>

<p>Nincs más hátra, mint egy megfelelő main.cpp-vel tesztelni ezt a rengeteg kódot, hogy egyáltalán működik-e ez az egész:</p>

<pre class="code prettyprint lang-c">#include &lt;string&gt;
#include &lt;iostream&gt;

#include &quot;cList.h&quot;

int main()
{
        cList&lt;int&gt; list1;
        list1 &lt;&lt; 1 &lt;&lt; 2 &lt;&lt; 3 &lt;&lt; 4 &lt;&lt; 5;
        int num;
        list1 &gt;&gt; num;
        std::cout &lt;&lt; num &lt;&lt; std::endl;

        cList&lt;char&gt; list2;
        list2 &lt;&lt; 'a' &lt;&lt; 'b' &lt;&lt; 'c' &lt;&lt; 'd' &lt;&lt; 'e';
        char chr;
        list2 &gt;&gt; chr;
        std::cout &lt;&lt; chr &lt;&lt; std::endl;

        cList&lt;std::string&gt; list3;
        list3 &lt;&lt; &quot;alma&quot; &lt;&lt; &quot;barack&quot; &lt;&lt; &quot;citrom&quot; &lt;&lt; &quot;dinnye&quot; &lt;&lt; &quot;eper&quot;;
        std::string str;
        list3 &gt;&gt; str;
        std::cout &lt;&lt; str &lt;&lt; std::endl;
}</pre>

<p>A fenti kód lefordítása majd futtatása után keletkezett kimenet legjobb esetben az, hogy 5, e, eper (mindegyik új sorban). Ezzel a sablonizációs bejegyzés végére is értünk, a legközelebbi alkalommal származtatni fogunk, ha a C++ istenei is így akarják.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/04/05/objektum-orientalt-cpp-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XSLT a gyakorlatban</title>
		<link>http://deadlime.hu/2006/03/03/xslt-a-gyakorlatban/</link>
		<comments>http://deadlime.hu/2006/03/03/xslt-a-gyakorlatban/#comments</comments>
		<pubDate>Fri, 03 Mar 2006 05:37:34 +0000</pubDate>
		<dc:creator>kriz</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[sablonok]]></category>
		<category><![CDATA[XPath]]></category>
		<category><![CDATA[XSLT]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2006/03/03/xslt-a-gyakorlatban/</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>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 <acronym title="eXtensible Stylesheet Language Transformation">XSLT</acronym>-vel kapcsolatban. Szóval ha az ember olyan trendi dolgokat használ, mint az <acronym title="Model, View, Controller">MVC</acronym>, 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 <acronym title="HyperText Markup Language">HTML</acronym> (vagyis inkább <acronym title="eXtensible Markup Language">XML</acronym>) szerű, ezért - szerintem - valamivel emberközelibb egy HTML-t ismerő ember számára, mint mondjuk a beágyazott <acronym title="Hypertext Preprocessor">PHP</acronym> 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.</p><span id="more-18"></span>

<p>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:</p>

<pre class="code prettyprint lang-xml">template.xml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;content&gt;
	&lt;title value=&quot;&quot;/&gt;
	&lt;url value=&quot;&quot;/&gt;
	&lt;content&gt;&lt;![CDATA[]]&gt;&lt;/content&gt;
&lt;/content&gt;</pre>

<pre class="code prettyprint lang-xml">template.xsl

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
	&lt;xsl:output method=&quot;xml&quot; encoding=&quot;utf-8&quot; indent=&quot;no&quot;/&gt;
	&lt;xsl:template match=&quot;/&quot;&gt;
		&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;hu&quot;&gt;
			&lt;head&gt;
				&lt;title&gt;&lt;xsl:value-of select=&quot;content/title/@value&quot;/&gt;&lt;/title&gt;
			&lt;/head&gt;
			&lt;body&gt;
				&lt;h1&gt;&lt;a href=&quot;{content/url/@value}&quot;&gt;&lt;xsl:value-of select=&quot;content/title/@value&quot;/&gt;&lt;/a&gt;&lt;/h1&gt;
				&lt;p&gt;&lt;xsl:value-of select=&quot;content/text&quot; disable-output-escaping=&quot;yes&quot;/&gt;&lt;/p&gt;
			&lt;/body&gt;
		&lt;/html&gt;
	&lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;</pre>

<p>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:</p>

<pre class="code prettyprint lang-php">/*
	'Tartalom' betöltése
*/
$content_xsl   = &amp;DOMDocument::load('template.xsl');
$content       = &amp;DOMDocument::load('template.xml');
$content_xpath = &amp;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 =&gt; $value) {
	if (!is_array($value)) {
		$content_xpath-&gt;query($path)-&gt;item(0)-&gt;nodeValue = $value;
	}
	else {
		foreach ($value as $key =&gt; $node) {
			$content_node = $content-&gt;importNode($node, true);
			$content_xpath-&gt;query($path)-&gt;item(0)-&gt;appendChild($content_node);
		}
	}
}

$proc = &amp;new XSLTProcessor();
$proc-&gt;importStylesheet($content_xsl);

print $proc-&gt;transformToDoc($content)-&gt;saveXML();</pre>

<p>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.<br/>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 <acronym title="Really Simple Syndication">RSS</acronym>-t is:</p>

<pre class="code prettyprint lang-xml">template.xsl

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
	&lt;xsl:output method=&quot;xml&quot; encoding=&quot;utf-8&quot; indent=&quot;no&quot;/&gt;
	&lt;xsl:template match=&quot;/&quot;&gt;
	&lt;rss version=&quot;2.0&quot;&gt;
		&lt;channel&gt;
			&lt;title&gt;Teszt RSS&lt;/title&gt;
			&lt;link&gt;http://www.something.com/&lt;/link&gt;
			&lt;description&gt;Ez egy teszt fájl a teszt RSS-nek...&lt;/description&gt;

			&lt;item&gt;
				&lt;title&gt;&lt;xsl:value-of select=&quot;content/title/@value&quot;/&gt;&lt;/title&gt;
				&lt;link&gt;&lt;xsl:value-of select=&quot;content/url/@value&quot;/&gt;&lt;/link&gt;
				&lt;description&gt;&lt;xsl:value-of select=&quot;content/content/text()&quot;/&gt;&lt;/description&gt;
			&lt;/item&gt;
		&lt;/channel&gt;
	&lt;/rss&gt;
	&lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;</pre>

<p>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á.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2006/03/03/xslt-a-gyakorlatban/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

