<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl"  href="/xslt/final.xslt"?><html>
  <head>
    <title>Codeigniter + XSLT (шаблонизаторы маздай!)</title>
    <meta name="css" content=""/>
    <meta name="js" content=""/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="id" content="18"/>
    <link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml"/>
  </head>
  <body>
    <div class="main">
      <div class="wrap">
        <div class="L">
          <h1><a href="/">..</a> / Codeigniter + XSLT (шаблонизаторы маздай!)</h1>
          <ol class="tags big"/>
          <div class="myContent"><p>Постоянная тема в CI, CakePHP,  Syphony и др. - как прикрутить шаблонизатор Имярек к фреймворку. В<a href="#" title="codeigniter.com/wiki/Category:Library::Template_Engine/" rel="nofollow" class="external"> wiki CodeIgnitera</a> насчитывается зоопарк из десятка с лишним шаблонизаторов.  В отличие от прочих,  XSLT является не сторонней библиотекой, а составной частью самого PHP5,  скорее всего поэтому, специального описания для него CI-wiki   нет.</p>
<p><a href="/article/12">Ранее</a>  я сделал заготовку для CMS с гордым названием "Codeigniter CMS Embrio "™. Вот эту заготовку я сейчас и использую для прикручивания XSLT к CI.  шаблонизатора.  Как обычно берем заготовку блога из директории step0 <a href="/doc/ci2.zip">архива</a>  (комментарии к заготовке <a href="/article/12">см. здесь</a>) Запускаем и убеждаемся что все работает.</p>
<p>Далее я чуть-чуть модифицирую контроллер для вывод ленты записей через XSLT. Вывод одиночных записей делается аналогично.</p>
<h2>1. Перевод массива в XML</h2>
<p>Из модели мы получаем массивы, которые обычно передаются во вьюер. Нам нужно перегнать эти массивы в XML. По-хорошему эта операция должна выполняться в модели (?), но для простоты я размещу это в контроллере, а модель оставлю без изменений.   В ней XML формируется обычной склейкой строк.</p>
<p>

<table class="code">
    <tbody>
        <tr>
            <td><!--php-->
            <pre class="brush: plain">/*  перевод массива простого запроса в XML  */
 function toxml($array)
    {
       $result="&lt;root&gt;   \n";
       foreach ($array as $key=&gt;   $value)
       {
           $result.="\t&lt;rec&gt;   \n";
           foreach ($value as $k=&gt;   $v) $result.="\t\t&lt;".$k."&gt;   ".$v."&lt;/".$k."&gt;   \n";
           $result.="\t&lt;/rec&gt;   \n";
       }
       return $result.="&lt;/root&gt;   \n";
    }
}</pre><!--/php--></td>
        </tr>
    </tbody>
</table>
</p>
<h2>2. XSLT трансформация</h2>
<p>Добавляем функцию трансформации. На входе - xml и имя шаблона xslt. Предполагается что шаблон лежит в директории  /xsl/</p>
<p>

<table class="code">
    <tbody>
        <tr>
            <td><!--php-->
            <pre class="brush: plain">function XSLT($xml,$tpl)
       {
                  /* xml -&gt;    dom */
                  $doc = new DOMDocument();
		  $doc-&gt;   loadXML($xml);
                  /* считываем xsl */
		  $xsl = new DomDocument();
		  $xsl-&gt;   load('xsl/'.$tpl.'.xsl');
                  
                  /* производим трансформацию */ 
		  $proc = new XsltProcessor();
		  $xsl = $proc-&gt;   importStylesheet($xsl);
		  echo $proc-&gt;   transformToXML($doc);
       }</pre><!--/php--></td>
        </tr>
    </tbody>
</table>
</p>
<h2>3. По шагам дорабатываем процедуру вывода ленты блога</h2>
<p>Для начала проверим что из себя представляет запрос к модели в виде xml</p>

<table class="code">
    <tbody>
        <tr>
            <td><!--php-->
            <pre class="brush: plain">function index()
	{
        /* обращение к модели за данными */
        $data = $this-&gt;   mblog-&gt;   getAll();
        /* преобразование массива в XML */
        $xml= $this-&gt;   toXML($data);
        echo $xml;
	}</pre><!--/php--></td>
        </tr>
    </tbody>
</table>
<p>После запуска блога в броузер выведется</p>

<table class="code">
    <tbody>
        <tr>
            <td><!--php-->
            <pre class="brush: plain">&lt;root&gt; 
	&lt;rec&gt;   
		&lt;id&gt;   1&lt;/id&gt;   
		&lt;title&gt;   Text1&lt;/title&gt;   
		&lt;author&gt;   Zalkind&lt;/author&gt;   
		&lt;mail&gt;   info@mail.ru&lt;/mail&gt;   
		&lt;anounce&gt;   Anounce1 &lt;/anounce&gt;   
		&lt;content&gt;   Text1 Text1 Text1&lt;/content&gt;   
	&lt;/rec&gt;   
	&lt;rec&gt;   
		&lt;id&gt;   2&lt;/id&gt;   
		&lt;title&gt;   Text2&lt;/title&gt;   
		&lt;author&gt;   Zalkind&lt;/author&gt;   
		&lt;mail&gt;   info@mail.ru&lt;/mail&gt;   
		&lt;anounce&gt;   Anounce2 &lt;/anounce&gt;   
		&lt;content&gt;   Text2 Text2 Text2&lt;/content&gt;   
	&lt;/rec&gt;   
    ............................................
    ............................................
    ............................................
    ............................................
    ............................................
&lt;/root&gt;   </pre><!--/php--></td>
        </tr>
    </tbody>
</table>
<p>Для преобразования его в HTML составим тривиальный XSLT-шаблон по типу того что лежит во /view/index.php</p>

<table class="code">
    <tbody>
        <tr>
            <td><!--php-->
            <pre class="brush: plain">&lt;?xml version="1.0" encoding="UTF-8"?&gt; 
&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"&gt;   
  &lt;xsl:template match="root"&gt;   
      &lt;html&gt;   
          &lt;head&gt;   &lt;link rel="stylesheet" href="/css.css" type="text/css" /&gt;   
          &lt;/head&gt;   
          &lt;body&gt;   
            &lt;xsl:apply-templates/&gt;   
          &lt;/body&gt;   
      &lt;/html&gt;   
  &lt;/xsl:template&gt;   
  &lt;xsl:template match="rec"&gt;   
     &lt;div class="entries"&gt;   
         &lt;h1&gt;   &lt;xsl:value-of select="title"/&gt;   &lt;/h1&gt;   
         &lt;div class="content"&gt;   &lt;xsl:value-of select="anounce"/&gt;   &lt;/div&gt;   
         &lt;a  class="right" href="/blog/view/{id}"&gt;   more&lt;/a&gt;   
     &lt;/div&gt;   
 &lt;/xsl:template&gt;   
&lt;/xsl:stylesheet&gt;   </pre><!--/php--></td>
        </tr>
    </tbody>
</table>
<p>в корневой директории создадим поддиректорю /xsl/  В нее сохраним этот шаблон с именем index.xsl</p>
<p>Далее еще раз скорректируем процедуру вывода блога</p>
<p>

<table class="code">
    <tbody>
        <tr>
            <td><!--php-->
            <pre class="brush: plain">function index()
	{
        /* обращение к модели за данными */
        $data = $this-&gt;   mblog-&gt;   getAll();
        /* преобразование массива в XML */
        $xml= $this-&gt;   toXML($data);
        /* вызов XSLT - трансформации */
        $this-&gt;   XSLT($xml,'index');
	}</pre><!--/php--></td>
        </tr>
    </tbody>
</table>
Теперь после запуска блога в броузере должно отобразиться то же самое что было до всех изменений, с той разницей что формирование выдачи идет уже через XSLT-трансформацию</p>
<h2>4. The End</h2>
<p>Все что написано выше - только простенький пример,  степень упрощения которого наверное черезмерна. В реальной практике все сложнее. Основна проблема XSLT - ресурсоемкость, поэтому для более-менее нагруженных приложений необходимо задумываться о многоуровневом кэшировании. Впрочем для всякой  фигни  с посещаемостью не более 50 хостов в сутки ( как например этот блог) кэширования не нужно. Да его здесь и нет.</p>
<p>И как обычно  все исходники можно найти в  директории step4 <a href="/doc/ci2.zip">архива</a></p></div>
          <ol class="tags big">
            <li class="date">2007-09-03</li>
          </ol>
          <ol class="see">
            <li>
              <a href="#"><span>rizhikov.habrahabr.ru/blog/18569/</span> - <b>Сергей Рыжиков. Иллюзии XML-XSLT технологий</b></a>
            </li>
            <li>
              <a href="#"><span>habrahabr.ru/blogs/about_cms/22018/</span> - <b>Сергей Котырев. Реабилитация XML/XSLT технологий</b></a>
            </li>
          </ol>
          <ul class="comment">
            <li id="a89" title="a0">
              <a name="XXX" title="" rel="10.09.08"/>
              <div>В  function toxml нужно рекурсию ввести. Тогда можно массивы любой вложенности обрабатывать. Заодно сделать проверку типа полей. Тогда можно теги заменять на атрибуты. Короче будет</div>
            </li>
            <li id="a91" title="a89">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="11.09.08"/>
              <div>Про рекурсию - в движке этого блога так оно и сделано. Хотя на практике не пригодилось. <br/>А вот по поводу атрибутов - вопрос спорный. Единообразия для я только id в атрибутах выдаю, <br/>Исходный XML этой страницы можно посмотреть добавив к адресу страницы "~xml"<br/>Впрочем как надо и как правильно я не знаю.</div>
            </li>
            <li id="a92" title="a0">
              <a name="Le capitaine Nemo" title="" rel="12.09.08"/>
              <div>в function XSLT криво вычисляется путь к директори с файлами XSLT. Нужно использовать константу APPPATH. Она даст путь к application.</div>
            </li>
            <li id="a108" title="a0">
              <a name="&#x410;&#x43D;&#x442;&#x43E;&#x445;&#x430;" title="" rel="02.10.08"/>
              <div>Хм.. зародил зерно сомнения.<br/>Автор, можешь в двух словах объяснить или на ссылку направить - в чём преимущество xslt перед шаблонизаторами? Зачем мы теряем в производительности и точно так-же делаем шаблон для каждой страницы? В чём высший смысл?</div>
            </li>
            <li id="a109" title="a108">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="02.10.08"/>
              <div>1. XSLT - стандарт, поддерживаемый W3 и всеми ведущими разработчиками.<br/>2. XSLT можно выполнять на клиенте.<br/>3. XSLT позволяет достичь максимальной гибкости при полном разделении данных от представления. <br/>4. XSLT имеет достаточно большое число расширений, позволяет строить свои библиотеки какой угодно сложности.</div>
            </li>
            <li id="a110" title="a109">
              <a name="&#x428;&#x422;&#x420;&#x410;&#x423;&#x421;" title="" rel="02.10.08"/>
              <div>п.2 - ерунда. Страницы не будут индексироваться.</div>
            </li>
            <li id="a111" title="a110">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="02.10.08"/>
              <div>Гонять туда-сюда представление - вот это ерунда. Представление должно быть отделено от данных. И пока альтернативы для XSLT в этом нет.<br/>С поисковыми машинами можно договориться если делать финальное преобразование на клиенте, а на сервере только промежуточное. См. например кишки этого сайта. <br/>При таком подходе можно вообще параллельно разрабатывать сайт и отлаживать функционал  до того как будет утвержден дизайн.</div>
            </li>
            <li id="a116" title="a0">
              <a name="Impr" title="biomonik.blogspot.com" rel="08.10.08"/>
              <div>Для того, что бы такой сайт работал, нужен браузер, способный осуществить трансформацию. Опера кстати не очень справляется с этим.</div>
            </li>
            <li id="a125" title="a116">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="10.10.08"/>
              <div>Сейчас даже Safari c Chrome  умеют парсить XSLT. Опера - начиная с 8.5. Если бы разработчики Оперы и др. не тормозили, может быть эта технология получила бы большее распространение. Нелюбимый публикой MSIE  мог это делать в 1998 году.</div>
            </li>
            <li id="a145" title="a0">
              <a name="Le capitaine Nemo" title="" rel="02.11.08"/>
              <div>Исрользовать в крупных проектах XSLT неаозможно. Очень большая нагрузка создается. Поэтому Smarty намного лучше</div>
            </li>
            <li id="a146" title="a145">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="02.11.08"/>
              <div>Яндекс - мелкий проект или крупный? Используют однако. <br/>Все упирается в квалификацию программистов. Имхо.</div>
            </li>
            <li id="a156" title="a146">
              <a name="Wordwild" title="" rel="11.11.08"/>
              <div>Он хотел сказать: в мелких проектах невозможно. Точнее нецелесообразно. Проще нечно smarty-подобное прикрутить.</div>
            </li>
            <li id="a158" title="a0">
              <a name="Le capitaine Nemo" title="" rel="12.11.08"/>
              <div>Спасибо за статьи. Пригодились. Продолжение будет?</div>
            </li>
            <li id="a160" title="a156">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="12.11.08"/>
              <div>Ну не знаю. По-моему он сказал то что хотел. Т.е. сложно использовать в нагруженных проектах. Но вроде как-то используют. <br/>А так проще то что знаешь. То что не знаешь - оно всегда сложнее. Мне Smarty сложнее. Или еще хуже - какой-нибудь самопальный движок без документации.</div>
            </li>
            <li id="a161" title="a158">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="12.11.08"/>
              <div>Не за что.<br/>Если про CodeIgniter - продолжения не будет. Я не программист. Этот цикл я писал исключительно для себя, когда была необходимость быстро-быстро сделать CMS для одного из своих проектов.<br/>Дальше вглубь лезть не имеет смысла - у меня не та квалификация.<br/>Если про XSLT - публикации будут. Надеюсь будет постоянный цикл "XSLT в примерах" и м.б. что-то еще.</div>
            </li>
            <li id="a300" title="a161">
              <a name="&#x439;&#x446;&#x443;&#x43A;" title="" rel="08.06.09"/>
              <div>жаль что продолжения не будет. вы хорошо пишете.</div>
            </li>
            <li id="a303" title="a0">
              <a name="GiN" title="www.borodatyh.net" rel="12.06.09"/>
              <div>Я кстати немного удивлен, что для CI нет готовых библиотек, которые используют XSLT как альтернативу дефолтовому шаблонизатору. Мне так и пришлось свой писать класс. Единственное, что меня не очень устраивает - так это то что трансформация происходит на стороне сервера. Ну буду думать дальшн. А вам спасибо за статьи.</div>
            </li>
            <li id="a304" title="a303">
              <a name="Le capitaine Nemo" title="" rel="12.06.09"/>
              <div>Не понимаю, зачем такая библиотека нужна. <br/>Хотя м.б. нужна библиотека sql to xml. Жаль что в mySQL этого пока нет. в MS это давно встроено.</div>
            </li>
            <li id="a364" title="a0">
              <a name="&#x412;&#x438;&#x442;&#x44F;" title="" rel="16.11.09"/>
              <div>XSLT - херня полная. Не используйте её, она излишня. И правильно что её нет в CI. Пользуйтесь либо нативным шаблоннотизатором, либо ещё лучше смарти.</div>
            </li>
            <li id="a365" title="a0">
              <a name="&#x41A;&#x43E;&#x441;&#x442;&#x438;&#x43A;" title="" rel="16.11.09"/>
              <div>Исаак Тынгылчав - просто гонит. Не говори то, в чём не разбираешься</div>
            </li>
            <li id="a366" title="a364">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="16.11.09"/>
              <div>Вы невнимательно читали. XSLT нет в CI. Его нет ни в каком другом PHP-фреймворке  потому что он - 1) является промышленным стандартомж 2) он _неотъемлемая_ часть PHP5 (Java, .NET) В отличие от выморочных разножопых шаблонизаторов.<br/>Можно сколько угодно спорить о том, насколько плох тот или иной стандарт. Насколько криво он реализован в броузерах. Но стандарт - это лучше чем недокументированная бредятина Васи Пупкина, даже если она гипернативная.</div>
            </li>
            <li id="a367" title="a365">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="16.11.09"/>
              <div>А более аргументировано?<br/>Мне приходилось работать с PERL,PHP,Java и .NET Единственное что объединяет эти четыре абсолютно разные платформы - XSLT. <br/>В PHP мне приходилось изучать как минимум 3-4 самых разных шаблонизаторва. Нафига?  Не понимаю.  Объясните. Зачем это нужно? <br/>Почему при смене фреймворка приходится усчить очередной шаблонизатор или искать как прикручивать какой-нибудь Smarty?</div>
            </li>
            <li id="a451" title="a0">
              <a name="Alex" title="" rel="19.02.10"/>
              <div>Спасибо за статью. Коротко и без излишеств. Весь интернет перерыл в поисках такой доступной статьи, как же применять XSLT. Везде целые книги про то, что это такое и ни слова о том, как заставить ЭТО работать на denwer-е)))<br/>Короче автору респект и уважуха :D</div>
            </li>
            <li id="a452" title="a451">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="19.02.10"/>
              <div>С денвером тысячу лент не работал, но там вроде XSLN по умолчанию включен.</div>
            </li>
            <li id="a459" title="a452">
              <a name="Alex" title="" rel="20.02.10"/>
              <div>Да тут не в Денвере дело, а как это все оформлено на сервере. Везде описывается браузерная обработка. И то в лучшем случае. Ооочень много букв про то, что это за штуковина (XSLT), что она умеет. Нигде наглядного примера применения. До этой статьи тупо не мог понять как привести механизм в действие)))</div>
            </li>
            <li id="a460" title="a459">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="20.02.10"/>
              <div>Ну не знаю. Применительно к CI или другому фремворку действительно нет ничего, а так сколько угодно текстов в Сети. <br/>Да и в книгах то же. Например в книгах  Дмитрия Котерова  (автор денвера) по php</div>
            </li>
            <li id="a465" title="a0">
              <a name="&#x421;&#x443;&#x43F;&#x435;&#x440;h&#x435;&#x440;&#x43E;&#x439;" title="" rel="05.03.10"/>
              <div>Интересная статься.<br/>по коментариям:<br/>XML - это наше будущее, см.Google.<br/>корпорации где важны данные, используют только XML язык.<br/>А примеров много 1С Бухгалтерия, Google планета, Google вся..., Ну и два года назад яндекс с ним - повторюшка.</div>
            </li>
            <li id="a577" title="a0">
              <a name="Novuscom" title="www.novuscom.ru/" rel="09.12.10"/>
              <div>Спасибо за статью. Хотелось бы больше примеров и более развернуто. Было бы круто. А то очень мало толковой информации и нормальным языком, как у вас.</div>
            </li>
          </ul>
        </div>
      </div>
      <div class="R">
        <a href="/" title="&#x41D;&#x430; &#x433;&#x43B;&#x430;&#x432;&#x43D;&#x443;&#x44E;"/>
      </div>
    </div>
    <div id="li"/>
  </body>
</html>

