Практический XSLT. Использование в качестве шаблонизатора

    В сети доступно масса документации по языку XSL. Данный раздел не претендует на роль документации по языку, а лишь кратко, по шагам объясняет, как создать свой XSLT-шаблон.

    Описанная ниже схема успешно мною используется уже более 3 лет. По началу я к XSLT относился с большой опаской (особенно, когда разбирал чужие исходники), однако однажды поняв, что к чему, уже не представляю, как без него можно работать.

    Рабочий стол

    Определим, что нам нужно для работы:
    • Входной XML-документ
    • XHTML-макет шаблона
    • Парсер XML для склейки XML с XSL

    У меня входной XML документ выдает CMS-система, в которой каждая страница с материалом собирается в XML-дерево.

    К XHTML-макету никаких ограничений нет. Есть лишь определенные рекомендации по верстке, которые позволят значительно сэкономить время на формирование шаблона.

    В качестве парсера (сборщика) конечного документа можно использовать браузер. Нужно лишь указать в XML-документы путь к файлу шаблону:
    <?xml-stylesheet type="text/xsl" href="template.xsl" ?>

    Хотя, как показала практика, этот механизм довольно глючный (мне пришлось пользовать IE). Лучше воспользоваться средствами XML-парсинга языка, на котором написана CMS-система. Я использую Parser (на нем, вообщем-то, у меня вся система и работает).

    Входной XML-документ

    Для начала разберемся со входным XML-документом. Для того, чтобы использовать XSL нужно иметь полное представление о его структуре.

    Я использую следующую схему:
    <?xml version="1.0" encoding="windows-1251"?>

    Начало

    <lang_table>
    />
    </lang_table>
    <item id="0" parent_id="0" is_published="1" section="1">
    Начало
    /

    <item id="1" parent_id="0" is_published="1" section="1">
    Новости
    news







    Обозначенный выше пример схемы не претендует на свою оптимальность. В силу тех или иных причин, мне он удобен. Но, обо всем по порядку.

    <?xml version="1.0" encoding="windows-1251"?> — заголовок XML-файла. Должен идти строго с начала файла. В нем прописана версия используемого XML-языка и кодировка документа. Я как правило работаю в windows-1251 (пока так удобнее), но, по идее UTF-8 лучше.

    - корневой элемент документа (можно придумать свое имя). Атрибуты:
    • Lang - язык документа. Нужен для создания мультиязычных шаблонов.
    • Id - идентификатор текущего раздела.

    <lang_table>
    - таблица языков, используемых на сайте.
    - блок элементов навигации:
    - блок основной навигации (основная структура сайта):
    <item id="0" parent_id="0" is_published="1" section="1">
    - элемент структуры сайта. Атрибуты:
    • Id - идентификатор раздела.
    • Parent_id - идентификатор родительского раздела.
    • Is_published - опубликован ли раздел.
    • Dir - uri-адрес раздела. По нему формируются полные адреса.
    • Section - тип раздела. Используется если необходимо разбить меню на основное и сервисное.

    - блок содержимого.
    В моей CMS используется модульная структура: все наполнение сайта представляет собой модули двух видов:
    • Html - текстовый модуль. Статические модули, которые заполняет редактор сайта.
    • Com - модуль-компонента. Динамические модули, которые формируют различные программные модули CMS: новости, статистика, поисковые блоки и т.д.

    В XSL-шаблонах есть разметка блоков, в которые можно размещать модули. Для определения блоков я использую простую нумерацию.

    CMS при сборке страницы просто выводит в все модули, которые задействованы на странице в виде:
    Атрибуты:
    • Id - идентификатор модуля.
      Container - блок-назначение (в каком блоке шаблона выводиться).
      Sorting - порядок вывода в блоке.
      Type - тип:
      • Com - модуль-компонентаю
        Html - текстовый модуль.

      Method - обработчик данных.
      Title - название модуля.
      DTD я практически не использую (лишь в самом общем виде):
      <!DOCTYPE site_page [

      <!ENTITY nbsp " ">
      <!ENTITY sect "§" >
      <!ENTITY copy "©">
      <!ENTITY laquo "«">
      <!ENTITY reg "®">
      <!ENTITY deg "°">
      <!ENTITY plusmn "±">
      <!ENTITY para "¶">
      <!ENTITY raquo "»">
      <!ENTITY times "×">



      <!ENTITY bull "•">
      <!ENTITY hellip "…">



      <!ENTITY ndash "–">
      <!ENTITY mdash "—">
      <!ENTITY lsquo "‘">
      <!ENTITY rsquo "’">
      <!ENTITY sbquo "‚">
      <!ENTITY ldquo "“">
      <!ENTITY rdquo "”">
      <!ENTITY bdquo "„">
      <!ENTITY lsaquo "‹">
      <!ENTITY rsaquo "›" >
      <!ENTITY euro "€">
      ]>

      Его можно вставить прямо в XML-документ. Сразу после <?xml version="1.0" encoding="windows-1251"?>.

      Подготовка XHML-шаблона


      XSL-шаблон создается на базе XHTML-шаблона (некой типовой страницы сайта). Код XHTML-страницы, при этом, должен быть валидным.

      Рассмотрим по шагам процесс создания шаблона.

      Проверив валидность XHML-страницы своего шаблона, для облегчения собственной работы, обозначьте в нем положение всех динамических блоков:
      • Меню (и других элементов навигации).
      • Информационных блоков страницы - то место в шаблоне, в котором будут выводиться модули сайта.
      • Заголовка/названия страницы.

      Сделать это лучше всего с помощью обычных HTML-комментариев:
      ...


      Администрирование сайта


      ...

      • Начало
      • Новости
      • Разделы


      ...

      Всякие новости

      ...

      Текст

      ...


      Основы описания XSL-шаблонов


      Все файлы XSL-шаблонов имеют следующий вид:
      <xsl:stylesheet version = '1.0' encoding="UTF-8"?>
      <xsl:template match="element">
      данные шаблона
      </xsl:template>
      </xsl:stylesheet>


      Где: <xsl:stylesheet version = '1.0' encoding="UTF-8"?> - определяет тип XML-документа и кодировку. Я использую UTF-8 (не спрашивайте, почему).
      <xsl:stylesheet> </xsl:stylesheet> - начало и конец XSL-документа.
      <xsl:template match="element"> </xsl:template> - начало и конец шаблона для элемента element.

      Шаблоны можно условно разделить на три вида:
      • <xsl:template match="element"></xsl:template> - шаблон, описывающий правила преобразования элемента element. Применяется автоматически ко всем элементам element.
      • <xsl:template match="element" mode="mode1"></xsl:template> - шаблон, описывающий правила преобразования элемента element в режиме mode1. Таким образом можно описать различные правила обработки элементов element.
      • <xsl:template name="template-name"></xsl:template> - шаблон с именем template-name. Не имеет привязки к какому-либо элементу XML-документа.

      Если элементы одного вида могут встречаться в различных частях структуры XML-документа (например, в XML-документе, формируемом системой элемент item используется повсеместно и имеет разное значение), то в шаблоне можно указать "структурный адрес" такого элемента:
      <xsl:template match="navigation/sections/item"></xsl:template>
      При этом, порядок применения шаблонов иерархичный, т.е., сначала шаблон применяется к корневому элементу, а затем, к дочерним, т.е. если мы вызвали обработчик для navigation, то для вызова обработчика для navigation/sections/item нам достаточно указать адрес sections/item.

      Структура папок шаблонов


      Для того, чтобы хранить на одном сайте несколько модулей необходимо как-то продумать структуру их хранения в папкам. При этом, удобнее разбить шаблоны на модули по нескольким xsl-файлам. Такой подход позволит в дальнейшем повторно их использовать при создании новых шаблонов.

      В простейшем варианте можно создать каталог xsl и там все складировать.

      Далее, чтобы внутри этого каталог шаблоны не путались (для каждого шаблона у нас получиться несколько файлов) создадим вложенные каталоги:
      • template_folder - каталог с файлами шаблона. Называть ее можно по имени шаблона, например my_template.
      • dtd - файлы описания основных сущностей. Могут быть полезными.
      • lang - шаблоны сообщений для различных языков (если на сайте используется их используется несколько).
      • mod - шаблоны модулей.

      Нам для начала потребуется создать каталог xsl/my_template и в нем, файл layout.xsl следующего вида:
      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE xsl:stylesheet SYSTEM "../dtd/entities.dtd">
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

      <xsl:template match="/node()">
      </xsl:template>

      </xsl:stylesheet>

      Где:
      <xsl:template match="/node()"> </xsl:template> - шаблон для элемента /node() (корневого). Вместо /node() можно указать //document, т.к. он у нас являеться корневым узлом.

      Копируем весь XHTML-код внутрь блока <xsl:template match="/node()"></xsl:template>

      Этот шаблон будет автоматически применяться ко всему XML-документу. В нашем случае, XSL-преобразование заменит весь XML-код на XHTML-код вашего шаблона.

      Далее, необходимо в директории XSL создать файл template.xsl (где, template - название вашего шаблона), в котором размещаем следующий код:
      <?xml version="1.0" encoding="UTF-8"?>
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

      <xsl:import href=" my_template /layout.xsl"/>
      </xsl:stylesheet>

      Где:
      <xsl:import href="my_template/layout.xsl"/>
      Директива импорта внешнего XSL-файла (обрабатываеться XSL-процессором) из указанного файла. Путь к файлу указываем относительный.

      Создание шаблона для основного навигационного меню


      Наш предыдущий шаблон не обладает никакой динамикой, т.к. просто заменяет весь выходной XML-документ на код нашего шаблона.

      Следующий шаг - создание шаблона для меню.

      Меню навигации сайта строиться на основе его структуры, представленной в XML-документе в следующем виде:

      <item id="0" parent_id="0" is_published="1" section="1">
      Начало
      /

      <item id="1" parent_id="0" is_published="1" section="1" hit="yes">
      Новости
      news




      Текущий раздел определяется по двум параметрам:
      • Атрибуту id у корневого элемента document - он всегда равен id текущего раздела.
      • Атрибуту hit у элемента item - если таковой имеется, то это значит, мы находимся на "главной странице раздела".

      Соответственно, для того, чтобы вывести меню сайта необходимо создать шаблон для элементов:
      • sections - корневой элемент меню.
      • item - элемент меню.

      При этом, необходимо учесть, что элементы item могут содержать другие элементы item, в том случае, если у раздела есть подразделы:




      1. Создаем в директории xsl/my_template файл navigation.xsl следующего вида:


      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE xsl:stylesheet SYSTEM "../dtd/entities.dtd">
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

      <xsl:template match="sections" mode="global_menu">
      </xsl:template>

      </xsl:stylesheet>


      2. Вставляем в шаблон код нашего меню из файла layout.xsl:



      <xsl:template match="sections" mode="global_menu">
      • Начало
      • Разделы
      • Новости

      </xsl:template>


      3. …а на его место в файле layout.xsl вставляем вызов нашего шаблона меню:



      <xsl:apply-templates select="navigation/sections" mode="global_menu"/>


      Где:
      select="navigation/sections" - относительный (относительно текущего) путь-адрес элемента. При этом, будут обработаны все элементы navigation/sections.

      mode="global_menu" - используем шаблон с режимом global_menu. Это нам нужно на тот случай, если нужно будет выводить еще и сервисное меню, отдельно, или "хлебные крошки", или что-еще другое на основе одной и той же ветки навигации.

      4. Плюс, добавим в файл layout.xsl директиву импорта файла шаблона navigation.xsl:


      <xsl:import href="navigation.xsl"/>

      5. Далее, создаем в файле navigation.xsl еще один шаблон, для обработки пунктов меню:



      <xsl:template match="item" mode="global_menu">
      <xsl:call-template name="href_attribute"/>
      <xsl:value-of select="title"/>


      </xsl:template>


      Где:
      <xsl:call-template name="href_attribute"/> - вызов шаблона по имени. При этом шаблон не имеет привязки к элементу, т.е. вызывается произвольно.

      <xsl:value-of select="title"/> - вставка-вывод значения элемента title текущего элемента. Если в параметре перед именем элемента поставить символ @ - выводиться будет значения атрибута текущего элемента.

      6. Немного изменяем шаблон sections:



      <xsl:template match="sections" mode="global_menu">

      </xsl:template>


      Где:
      <xsl:apply-templates select="item" mode="global_menu"/> - обработка всех элементов item элемента sections. При этом, элементы item самих элементов item (sections/item/item) обрабатываться не будут, т.е. выводиться только один уровень меню разделов.

      Мы вынесли обработку элементов item (пунктов меню) в отдельный шаблон. При этом, в нем мы добавили еще и вызов другого шаблона: <xsl:call-template name="href_attribute"/>

      Этот шаблон будет формировать нормальные uri-ссылки для элементов нашего меню. О нем немного позже.

      7. Теперь нам необходимо доделать меню,


      чтобы оно учитывало, какой раздел является текущим. Для этого нам придется добавить условную обработку в наш шаблон элемента item:

      <xsl:template match="item" mode="global_menu">

      <xsl:choose>

      <xsl:when test="descendant-or-self::*/@id = /node()/@id">
      <xsl:value-of select="title"/>
      </xsl:when>

      <xsl:otherwise>
      <xsl:call-template name="href_attribute"/>
      <xsl:value-of select="title"/>

      </xsl:otherwise>
      </xsl:choose>

      </xsl:template>


      Здесь мы сталкиваемся с новой конструкцией:
      <xsl:choose>
      <xsl:when></xsl:when>
      <xsl:otherwise></xsl:otherwise>
      </xsl:choose>

      …которая, собственно, и задает условную обработку XML-элементов. В качестве параметра мы задаем условие: <xsl:when test="descendant-or-self::*/@id = /node()/@id">

      В нашем случае это условие равенства атрибутов ID у корневого элемента (document) и текущего элемента (item), которое и определяет, является ли элемент текущим.

      Внутри блока <xsl:when></xsl:when> располагается то, что выводиться в случае выполнения условия. В блоке <xsl:otherwise></xsl:otherwise> - если условие не выполняется.

      8. Теперь, разберем шаблон href_attribute:



      <xsl:template name="href_attribute">
      <xsl:attribute name="href">
      <xsl:text>/</xsl:text>
      <xsl:for-each select="ancestor-or-self::item">
      <xsl:value-of select="dir"/>
      <xsl:text>/</xsl:text>
      </xsl:for-each>
      </xsl:attribute>
      </xsl:template>


      Здесь мы сталкиваемся с инструкцией xsl:attribute. Она позволяет создавать атрибуты для элементов внутри которого она вызывается. В нашем случае мы вызываем ее из элемента a, соответственно, она создаст для него атрибут href, т.е. адрес.

      Инструкция <xsl:for-each select="ancestor-or-self::item"> задает цикл обработки для всех элементов, удовлетворяющих условию. В нашем случае мы выбираем ancestor-or-self::item - ось элементов от корневого элемента до текущего по цепочке. В нашем случае это позволяет выбрать для всей цепочки узлы dir, т.е. построить полный адрес текущего узла-раздела.

      Далее, нам необходимо каким-то образом определить, как у нас будут обрабатываться модули содержимого. Но, об этом в следующий раз.

      UPD:
      Материалы к статье. Собрал из того, что было:
      parser.proc.ru/iso/xslt-1.zip

      В шаблоне все пути прописаны от корня (делал на основе шаблона работающего на реальном сайте) поэтому либо перепишите их на относительные либо запускайте из под Apache.

      В архиве входной XML-документ лежит в /xsl/document.xml
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 100
    • 0
      Спасибо! Интересно изложили..
      • +2
        Отлично, как давно я искал такой мануал. Всё по делу и ничего лишнего. Огромное спасибо!
        • +3
          Спасибо, хорошая статья!

          Мне во многих проектах доводилось плотно заниматься xsl-трансформацией. За это время накопились несколько замечаний, которые стоит учесть при выборе этой технологии.

          1. тормозит
          Нельзя сказать, что безумно, но если дело доходит до оптимизации скорости ответа сервера — xsl-трансформация окажется одним из самых «узких» мест. Можно писать «правильные» шаблоны и со временем научиться «разгонять» скорость их обработки. Но значительного прироста в скорости это не принесет. В последнем проекте это сыграло решающую роль и пришлось отказаться от xsl вообще.


          2. нет четкой структуры. В случае большого объема кода приходится изобретать и постоянно придерживаться четких правил для вложенности шаблонов. Встроенных средств для этого нет.

          3. верстальщики не знают xsl. Это заметно осложняет последующую поддержку проекта.
          • +5
            1. Для того чтобы не тормозило надо использовать кеширование.
            2. Четких правил придерживаться стоит всегда.
            3. Плохие верстальщики не хотят знать XSL. Хороших можно научить.
            • 0
              Согласен по всем пунктам, однако:

              1. действительно это один из способов «разгона», но если страница на 100% динамическая — помогает мало.
              2. это гораздо удобней делать, когда правила встроены в технологию или даже диктуются на уровне синтаксиса.
              3. к сожалению кадровой политикой везде занимались другие люди и большого выбора верстальщиков не было.

              Да вобщем-то верстальщиков тоже можно понять — они шли верстать макеты в хтмл, ну максимум править шаблоны очень похожие на хтмл, а сложный хсл шаблон достаточно далек от результирующего хтмл'я.

              И кстати, «я за наших!» т.е. мне нравится xsl и интересно было с ним работать. Но есть моменты на которые необходимо обратить внимание при выборе технологии. Т.к. отказаться от xsl, когда проект уже практически готов будет очень сложно.
              • +4
                Плох тот верстальщик, который не хочет научиться большему ) Я вобще против такой профессии. Более уместно будет Front-End Web Developer, тут даже само название обязывает знать больше чем просто верстка. )

                А в плане технологий - все просто и неоднократно оговорено. Технологию надо выбирать в зависимости от нужд проекта, а не в зависимости от самой технологии. Это как "php-программист" )
                • 0
                  не нужно решать за людей чему им учиться.
                  человек имеет право решать - нужно ему это или нет.

                  знания xsl скорее нужны девелоперу, и как результат, грамотного верстальщика может просто не оказаться под рукой когда он нужен ( девелоперы обычно заняты на 120%)
                  • НЛО прилетело и опубликовало эту надпись здесь
                    • –1
                      Именно поэтому есть такая профессия - верстальщик
                    • +1
                      Во-первых вы невнимательно прочитали мой комментарий. Девелоперы тоже делятся на Front-End и Back-End.

                      Во-вторых вы видимо не имели дело с XSLT. Никто при разработке больших проектов не будет верстать все в статике, а затем просить "девелопера" переводить все на XSLT-шаблоны. Это бессмысленая трата времени.

                      XSLT имеет самое прямое отношение к верстке и является частью Front-End'a.

                      Кроме того, я ни за кого ничего не решаю, каждый сам себе Прокруст. И вы, пожалуйста не решайте, что мне говорить, а чего не стоит.
                      • 0
                        Никто при разработке больших проектов не будет верстать все в статике, а затем просить "девелопера" переводить все на XSLT-шаблоны.

                        Мне кажется это разного плана задачи - одно дело отладить сверстанный дизайн под все браузеры, другое дело связать с бекэндом.
                        • –1
                          На счет больших проектов - вы не поверите что там происходит :) Там и HTML в базу кладут и еще похлеще вытворяют. Знаю, участвовал и да сих пор общаюсь с людьми, которые делают проекты для Билайна, Боинга и других крупных корпораций.

                          Далее, "не будет верстать все в статике, а затем просить "девелопера" переводить все на XSLT-шаблоны".
                          Простите, а Вы стадию прототипирования начисто игнорируете? И frontend и backend "по-живому" делаете? Не хочу в это верить, боюсь я таких людей :)

                          Ну и по последнему - я не указываю Вам, тут все выражают мнение. Обратите внимание, я как раз и писал о том что каждый выбирает сам. Это Вы пытаетесь указать "Плох тот верстальщик, который не хочет научиться большему", что как я вижу есть принуждение.

                          P.S. XSLT нужно применять осторожно и с умом. И только когда это оправдано.
                          • +1
                            Я хорошо знаю что происходит в больших проектах, так как принимаю в них непосредственное участие. И думаю что все зависит от компании и работников.

                            Backend'ом я не занимаюсь, а frontend сразу начинаю с XSLT, это гораздо удобнее, по крайней мере в моей компании. Прототипирование здесь не причем. Это более ранняя стадия.

                            Если вы считаете что мои слова - принуждение, то скажу более глобально. Плох тот разработчик, который не хочет учиться чему-то новому. Разработчика, который считает что он уже все знает, надо гнать в шею.

                            По поводу технологий согласен и повторюсь. Цель определяет средства, а не наоборот.
                            • 0
                              Можите привести примеры крупных проектов с примением XSLT?
                              • +1
                                Давайте в личке продолжим, ок? )
                                • 0
                                  Почти все проекты Яндекса, чего далеко ходить.
                        • 0
                          Правильная позиция. Нет смысла плодить узких специалистов. Пусть специалист будет узким пока он ничего не умеет. А с таким подходом специалисты не хотят ничему учиться, потому что это не их область, они, видите ли пришли на html-верстальщиков.
                        • 0
                          Я верстальщик с двухлетним стажем, очень жажду изучить XSL, но на работе так заваливают рутино, что времени вообще ноль.
                          • 0
                            Почитайте http://www.zvon.org/xxl/XSLTutorial/Outp…
                            Мне хватило недели, чтобы разобраться.
                            • 0
                              хм, забавно... через полгода работы с XSLT 2.0 (Saxon) я понял что я бог и могу делать на нем все, через год до меня дошло что я не знаю ключевых моментов даже XSLT 1.0, через полтора я каждый раз сомневаюсь в разумности использования той или иной конструкции, и каждый день сулит все новые и новые открытия, и день когда я скажу что разобрался с XSLT по-моему никогда не наступит...

                              впрочем, это исключительно проблемы моего собственного мозга, у вас конечно все получится намного быстрее)
                              • 0
                                Уже ничего на этом сервере нет, на главной высвечивается - "It works!", надеюсь что временно.
                                • +1
                                  Смотрю - все есть... идите прямо по ссылке.
                                  • 0
                                    Заработал сайт, это радует :)
                            • НЛО прилетело и опубликовало эту надпись здесь
                              • 0
                                не знаю, что у вас за шаблоны, но свои я оцениваю как достаточно сложные (потому как результирующее DOM дерево после формирования еще раз обрабатываеся внутри xslt, но и не только) и формирование документа из моего шаблона занимает от одной до четырех сотых секунды. шаблоны все в распарсенном состоянии хранятся в памяти, системы - suse linux 10.1 на pentium d 2.8 GHz и mac os x 10.5 на core 2 duo 2.33 GHz, везде последние libxml2 & libxslt
                            • 0
                              Верстальщики не знают ничего кроме верстки, всему надо учить, и лучше один раз научить XSLT.
                            • 0
                              спасибо за статью!
                              было бы очень удобно скачать все файлы статьи одним архивом... хотя бы открыть в любимом xslt-редакторе (подсветка, навигация и т.п.)
                              • +2
                                Собрал из того, что было:
                                http://parser.proc.ru/iso/xslt-1.zip

                                В шаблоне все пути прописаны от корня (делал на основе шаблона работающего на реальном сайте) поэтому либо перепишите их на относительные либо запускайте из под Apache.

                                В архиве входной XML-документ лежит в /xsl/document.xml
                                • 0
                                  оу, даже с картинками =)
                                  many thanks!
                                  • 0
                                    Поместите это в конце статьи, чтобы людям не пришлось искать в комментариях.
                              • 0
                                Спасибо, интересно, подробно и познавательно! Классная статья.
                                Но только одно замечание - вы забыли, как и все сторонники хслт, о самом важном вопросе, а именно: "нахрена козе баян?"
                                Система тратит время как на составление хмля, так и на его же парсинг, а где же плюсы? Каково принципиальное отличие от тех же пхпшных шаблонизаторов, от того же популярного смарти?
                                • +1
                                  Цель статьи ответить на вопрос: Как? а не Зачем.
                                  • +2
                                    Иначе получиться очередной холивар. Всегда должен быть выбор. Я свой сделал. Однако, я не собираюсь никого убеждать в оптимальности своего выбора. Просто он такой.

                                    По тем же причинам я использую
                                    - Parser, а не PHP
                                    - Xara, а не Corel или Illustrator.
                                    ... список можно продолжать дальше.
                                    • 0
                                      Не смешите, хотите сказать, что смарти отличается большой производительностью?
                                      • 0
                                        Грамотно настроенная и на небольших проектах - да. Возможно и на средних нормально покажет себя.
                                      • НЛО прилетело и опубликовало эту надпись здесь
                                        • –1
                                          Каково принципиальное отличие от тех же пхпшных шаблонизаторов, от того же популярного смарти?


                                          приниципальное - трансформации можно гонять на клиенте а не на сервере ;)

                                          хотя на практике мало кто этим пользуется...
                                          • НЛО прилетело и опубликовало эту надпись здесь
                                            • 0
                                              ну... я же про принципиальное отличие, а не про плюсы/минусы/проблемы ;)
                                              • НЛО прилетело и опубликовало эту надпись здесь
                                          • 0
                                            XSLT дает очередную возможность отделения мух от котлет, притом полную, сам стараюсь работать только с xslt, простейший пример: есть XML и его можно вывести как заполненную форму так и просто как два дива, плюс при выводе вида не надо заморачиваться с экранированием спец символов.
                                            P.S. Русские примеры xml/xpatch/xslt немного посеченгная версия английской версии. И, по хорошему, кучу нюансов эти примеры не отражают, искал в свое время некоторые решения по маленьким кусочкам, так что куча документации - это громкие слова
                                          • 0
                                            спасибо, за статью, есть вопросик - почему именно шаблоны lang, как мне кажется в случае локализации лучше всего поможет именно dtd?
                                            • 0
                                              В настоящее время у меня для разных языков используются специальные xsl-таблицы. С ними проще работать чем с DTD. Кроме того, я сейчас пытаюсь перевести все на динамические XSL-шаблоны, которые формируются индивидуально для каждого пользователя.
                                              • 0
                                                не вижу особых проблем написать в dtd <!ENTITY site.about.title "Привет мир">,
                                                а потом в шаблоне <xsl:text>&site.about.title</xsl:text>, а каким образом Вы делаете вызов разных таблиц для разных локалей, через call-template или apply-template?
                                                • 0
                                                  Можно. Попробую. Но будут проблемы, если мне нужно вставлять что-то вроде:

                                                  184209, Мурманская обл., г. Апатиты, ул.Такаято,
                                                  <br />
                                                  <a href="mailto:mail@domen.ru"><a href="mailto:mail@domen.ru">mail@domen.ru</a></a>

                                                  Насчет вызова разных таблиц - напишу в следующей статье. Там много тонкостей.
                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                            • +1
                                              <xsl:template match="/node()"> </xsl:template> - шаблон для элемента /node() (корневого). Вместо /node() можно указать //document, т.к. он у нас являеться корневым узлом.

                                              меня немного пугают используемые вами xpath-выражения, если вы хотите взять корневой элемент почему бы не сделать это хотя бы так match="/document", во втором случае (//document) процессор не остановится на первом элементе, а продолжит бежать по всему дереву в поисках элемента document, а оно вам надо? старайтесь использовать // как можно реже, вы теряете в производительности
                                              • 0
                                                У меня используется /node().
                                                //document я указал, т.к. /document подглючивал у меня сегодня в IE.

                                                Насчет // - согласен.
                                                • +1
                                                  лично для себя я считаю хорошей практикой начинать с корня

                                                  <xsl:template match="/">
                                                  <xsl:apply-templates />
                                                  </xsl:template>

                                                  а дальше уже обращаться ко всем элементам самым простым способом

                                                  <xsl:template match="document">
                                                  ...
                                                  </xsl:template>

                                                  но это уже каждый сам для себя решает, что хорошо, а что плохо)
                                                  • 0
                                                    Раньше я так и делал, но когда схема документа "разрослась" стал называть все, чтобы было проще самому читать свой код.
                                              • –2
                                                Подходит для относительно небольших страниц, на которых в основном статический контент. Если что-то больше - лучше использовать native php или шаблонизатор на компилируемом языке, например Си.
                                                • 0
                                                  Идеология очень хороша, практикую уже 2 года. Но есть проблема: шаблонизированные формы, т.е. элементы form, которые обёрнуты в шаблон XSLT. Так вот, при отправке методом POST, поля такой формы не передаются серверу из Opera. Из FF и IE передаются, но исключительно в UTF-8, какой-бы чарсет ни был установлен.
                                                  Если кто-нибудь разобрался с этим, пожалуйста, поделитесь решением.
                                                  • 0
                                                    Странно. Попробуйте зайти на http://parser.proc.ru/forum/ (там все на XSLT)
                                                    Я оперой давно не пользуюсь, поэтому скатать четко не могу, но проблем быть не должно.
                                                    • 0
                                                      Решение есть такое:
                                                      <xsl:output method="xml"
                                                      ...
                                                      />
                                                      Именно из-за этого я делаю один шаблон для Оперы и еще один для остальных браузеров.
                                                      Ну а вообще в Опере 9.5 это уже поддерживается.
                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                      • 0
                                                        насчет node() я писал немного выше - я не утверждаю, что так и надо. Просто мне пока так удобнее читать: выбираем корневой узел.

                                                        Про <xsl:variable name="current-section" select="/*/@id" /> я постараюсь поговорить позже. Это действительно удобнее. Просто, нужно будет еще объяснить переменные XSL.

                                                        Насчет ul id="main-menu" - эта конструкция более валидная, чем <menu>
                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                      • +1
                                                        В чем преимущество парсинга при помощи браузера? А в том, что пользователь один раз загрузит xsl-шаблон для страницы (т.е. по сути всю разметку) и потом будет подгружать только данные из xml. Работает это очень и очень быстро.

                                                        Минуса два. Первый - это то, что постоянно сталкиваешься с тем, что в каком-нибудь браузере что-то из xslt не реализовано. Конечно, чаще всего этим браузером становится Опера:) И второй минус - Яндекс не индексирует сделанные таким образом сайты. Т.е. бот заходит, но не индексирует. В чем проблема - пока не знаю. Буду очень признателен, если кто-нибудь поделится своим опытом в этой связи.
                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                          • 0
                                                            Дак в том-то и дело. Что я сделал выходной xml-файл так, что он выглядит как обычный html со всеми head, body. Ни одного не-html-ного тега нет. Только в начале да подключается xsl.
                                                            Т.е. я сделал тупо текстовую версию сайта со всеми ссылками, переходами. Гугл захавал - я смотрю в кеше и вижу то, что и задумывал. Но вот яндекс, зараза...
                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                              • 0
                                                                Возможно дело в Content-Type, Яндекс не хочет брать text/xml? Но без него браузер не будет правильно обрабатывать.
                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                  • 0
                                                                    Да вопрос задавался еще черт-те когда. А ответить соизволили как раз сегодня. Таки да, не поддерживает их робот Content-Type: text/xml.
                                                                    Но зато они разрешили делать подмену заголовка специально для их робота - надо будет на стенку в рамочке повесить как официальное разрешение на клоакинг от яндекса:)
                                                              • 0
                                                                Спасибо за статью, будем ждать продолжения :)

                                                                не в тему:
                                                                когда уже Хабр будет код подсвечивать и форматировать, а?
                                                              • 0
                                                                Огромное спасибо за отличнейшую статью. Сам использую XSLT вот уже 3-й год весьма нравится. весьма быстро и удобно. Но мало еще народа переходит в сайтостроительстве на него, я надеюсь что после таких статей наших прибавится.
                                                                • 0
                                                                  Как с помощью xslt вывести список в два столбца ?
                                                                  например есть список:
                                                                  <list>
                                                                  <item>1</item>
                                                                  <item>2</item>
                                                                  <item>3</item>
                                                                  <item>4</item>
                                                                  <item>5</item>
                                                                  <item>6</item>
                                                                  </list>
                                                                  Как его преобразовать в такое:
                                                                  <table>
                                                                  <tr>1<td></td><td>4</td></tr>
                                                                  <tr>2<td></td><td>5</td></tr>
                                                                  <tr>3<td></td><td>6</td></tr>
                                                                  </table>
                                                                  ???
                                                                  • 0
                                                                    использовать count(list/item) и в зависимости от этого строить нужное кол-во столбцов и строк в них.
                                                                    • 0
                                                                      Если вам нужны _визуальные_ столбцы, может, лучше использовать CSS и свойства float+width?
                                                                      • 0
                                                                        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

                                                                        <xsl:template match="/list">
                                                                        <table>
                                                                        <xsl:apply-templates select="item[count(preceding-sibling::item) <= count(following-sibling::item)]" mode="tr"/>
                                                                        </table>
                                                                        </xsl:template>

                                                                        <xsl:template match="item" mode="tr">
                                                                        <xsl:variable name="pos" select="ceiling(count(../item) div 2)"/>
                                                                        <tr>
                                                                        <xsl:apply-templates select="." mode="td"/>
                                                                        <xsl:apply-templates select="following-sibling::item[$pos]" mode="td"/>
                                                                        </tr>
                                                                        </xsl:template>

                                                                        <xsl:template match="item" mode="td">
                                                                        <td><xsl:value-of select="."/></td>
                                                                        </xsl:template>

                                                                        </xsl:stylesheet>
                                                                        • 0
                                                                          вместо "<=" конечно же нужно поставить "&lt;="
                                                                      • –1
                                                                        XML:



                                                                        1
                                                                        2
                                                                        3


                                                                        XSLT:




















                                                                        В браузере открывать XML, XSLT-шный файл обозвать transform.xsl и бросить тудаже где файл.xml
                                                                        • 0
                                                                          Когда код посылаете, нажимайте "предпросмотр", т.к. неясно как его хабр отформатирует.
                                                                          Символы "<" нужно заменить на "&lt;"
                                                                          Сам код лучше обернуть в <code>...</code>.
                                                                        • –1
                                                                          ЕМАЕ! УЖАС КАКОЙ!!!! :D
                                                                          Откуда такие грабли?

                                                                          XML:

                                                                          <?xml version="1.0" encoding="Windows-1251"?&rt;
                                                                          <?xml-stylesheet type="text/xsl" href="transform.xsl"?&rt;
                                                                          <list&rt;
                                                                          <item&rt;1</item&rt;
                                                                          <item&rt;2</item&rt;
                                                                          <item&rt;3</item&rt;
                                                                          </list&rt;

                                                                          XSLT:

                                                                          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&rt;
                                                                          <xsl:output method="html" encoding="windows-1251" doctype-system="http://www.w3.org/TR/html4/strict.dtd" doctype-public="-//W3C//DTD HTML 4.01//EN"/&rt;

                                                                          <xsl:template match="/list"&rt;
                                                                          <html&rt;
                                                                          <body&rt;
                                                                          <table&rt;
                                                                          <xsl:for-each select="item[(position() - 1) mod 2=0]"&rt;
                                                                          <tr&rt;
                                                                          <td&rt;<xsl:value-of select="./text()" /&rt;</td&rt;
                                                                          <td&rt;<xsl:value-of select="following-sibling::item/text()" /&rt;</td&rt;
                                                                          </tr&rt;
                                                                          </xsl:for-each&rt;
                                                                          </table&rt;
                                                                          </body&rt;
                                                                          </html&rt;
                                                                          </xsl:template&rt;

                                                                          </xsl:stylesheet&rt;
                                                                          • 0
                                                                            Господи!!!!
                                                                            Почему так криво то??? Какая нафиг подсветка синтаксиса, если оно простое то схавать не может?!!! Охренеть можно.... Раз в 5 минут и так криво!!! :D :D :D Я понимаю что надо предпросмотр юзать - но некогда мне - быстро написал пример и отправил.... Блин! Господа владельцы сайта, давайте я вам дам код для текстарии?? :D
                                                                            • 0
                                                                              Это решение задачи в другом направлении, где будет на выходе получаться
                                                                              1 - 2
                                                                              3 - 4
                                                                              5 - 6

                                                                              Требовалось же
                                                                              1 - 4
                                                                              2 - 5
                                                                              3 - 6
                                                                              что сложнее
                                                                              • 0
                                                                                ага, недочитал - пример не посмотрел... но можно тоже на фориче рализовать в принципе
                                                                          • 0
                                                                            В коде много переменных, но за счет них он работает в IE.

                                                                            <xsl:variable name="totalItems"><xsl:value-of select="count(//list/item)"/></xsl:variable>
                                                                            <xsl:variable name="totalItemsHalf"><xsl:value-of select="$totalItems div 2"/></xsl:variable>

                                                                            <xsl:template match="//document">
                                                                            <html>
                                                                            <body>

                                                                            <table border="1">
                                                                            <xsl:apply-templates select="//list/item" mode="list"/>
                                                                            </table>

                                                                            </body>
                                                                            </html>
                                                                            </xsl:template>

                                                                            <xsl:template match="item" mode="list">
                                                                            <xsl:variable name="cur">
                                                                            <xsl:value-of select="position()"/>
                                                                            </xsl:variable>
                                                                            <xsl:variable name="next">
                                                                            <xsl:value-of select="$totalItemsHalf + $cur"/>
                                                                            </xsl:variable>
                                                                            <tr>
                                                                            <xsl:choose>
                                                                            <xsl:when test="position() > $totalItems div 2"></xsl:when>
                                                                            <xsl:otherwise>
                                                                            <td><xsl:value-of select="text()"/></td>
                                                                            <td><xsl:value-of select="parent::*/item[position() = $next]/text()"/></td>
                                                                            </xsl:otherwise>
                                                                            </xsl:choose>
                                                                            </tr>
                                                                            </xsl:template>


                                                                            А так, если использовать CGI-склеивание XML с XSL то код получиться короче
                                                                            • 0
                                                                              И смысл использования трансформации на клинете, если придется так извращаться? :)
                                                                              Если трансформер не поддерживает стандарт, то не надо его использовать, это будет мучение одно.
                                                                              • 0
                                                                                Я привел пример для тех, у кого нет возможности по быстрому настроить CGI трансформацию. Этот пример можно просто загрузить в браузер и посмотреть.

                                                                                Для рабочих проектов можно использовать все средства XSLT. В этом случае код уменьшается в разы и легче читается.

                                                                                Я не говорю, что нужно использовать трансформацию на клиенте. Для этого пока нет достаточной поддержки со стороны браузеров.
                                                                            • +1
                                                                              подсказка:
                                                                              match="item[position() div 2 = 1]"
                                                                                • 0
                                                                                  о-о-о... что то это мне напоминает одно тестовое задание :)
                                                                                  я прав?
                                                                                • 0
                                                                                  XSLT на фронтенде пока зло. На РИТе помнится было смешно, когда про это рассказывал Кудинов (вроде).
                                                                                  Забили помидорами под корень.
                                                                                  • 0
                                                                                    А под фронтендом вы здесь подразумеваете клиент/браузер я так понимаю... чтобы почувствовать зло его ведь надо вкусить не так ли?.. вы его вкусили?.. надеюсь что нет. Мне, вот, повезло меньше, я вкусил, но, должен сказать, зло оказалось не таким уж противным на вкус))

                                                                                    Взять, к примеру, проблему индексации "сайта с XSLT на клиенте" поисковиками, проблема? согласен. А как насчет бэк-офисов, интранет-систем? если вы решаете задачу в этих рамках, то проблем с индексацией у вас уже нет, потому что она там не нужна. Видите, одним злом сразу стало меньше. Нужно просто поискать правильную сферу применения.

                                                                                    Что касается РИТа, то я на нем не был, но я смотрел запись этого доклада, мне он смешным не показался, мне он показался очень любопытным. Интересно, а как вы оцениваете ваши собственные доклады, уважаемый Flack?
                                                                                    • 0
                                                                                      Шо ж вы серьезный-то такой.
                                                                                      Нет, я неделаю интранет-проектов. Не интересно мне как-то. Так что для меня неиндексируемая технология не существует, уж извините :)

                                                                                      Я говорил не про доклад, а про обсуждение.
                                                                                      • 0
                                                                                        ну как можно обвинять в серьезности человека с такой аватаркой))

                                                                                        просто ваше утверждение звучит уж очень безапеляционно, мне захотелось немного его расшатать, и я не являюсь адвокатом Кудинова, но фраза показалась мне не очень дружелюбной)

                                                                                        P.S. Ты же сам докладчик, Лёха) прикинь, я напишу: было смешно, когда про это рассказывал Рыбаков (вроде)................ без обид)
                                                                                        • 0
                                                                                          Я всегда стараюсь рассказывать, чтобы было смешно
                                                                                          • 0
                                                                                            все, уложил на лопатки, я сдаюсь)
                                                                                    • 0
                                                                                      я рассказывал, и сам же сказал что делать этого не стоит (если ты не делаешь админку под себя или интранет) и объяснил почему.
                                                                                      а вопрос этот обсуждается и сейчас, а толковой информации как небыло так и нет.
                                                                                      • 0
                                                                                        Вопрос исключительно в удобстве: каму как. Мне удобно. Многим нет. Раньше тоже считал это бредом, пока не "попробовал". Теперь у меня вся CMS-ка работает на XSLT: и админка и сам сайт. При этом, алгоритм "сборки" для обоих частей CMS един.
                                                                                      • 0
                                                                                        и не на РИТе, а ClientSide
                                                                                        • 0
                                                                                          На Рите, на Рите.
                                                                                          • 0
                                                                                            хм... интересно :)
                                                                                            как хоть назывался? и кто читал? а то Кудинова я в докладчиках не нашел. или это было в 2007?
                                                                                        • 0
                                                                                          Хех… хабр весь исходный код поел((
                                                                                          Fade, не дадите ссылку на эту статью на другом сайте, где такой беды не приключилось?)

                                                                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.