Практический 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
    Share post

    Comments 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%)
                  • UFO just landed and posted this here
                      –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
                                    Заработал сайт, это радует :)
                            • UFO just landed and posted this here
                                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
                                      Ok.
                                  0
                                  Спасибо, интересно, подробно и познавательно! Классная статья.
                                  Но только одно замечание - вы забыли, как и все сторонники хслт, о самом важном вопросе, а именно: "нахрена козе баян?"
                                  Система тратит время как на составление хмля, так и на его же парсинг, а где же плюсы? Каково принципиальное отличие от тех же пхпшных шаблонизаторов, от того же популярного смарти?
                                    +1
                                    Цель статьи ответить на вопрос: Как? а не Зачем.
                                      +2
                                      Иначе получиться очередной холивар. Всегда должен быть выбор. Я свой сделал. Однако, я не собираюсь никого убеждать в оптимальности своего выбора. Просто он такой.

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


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

                                            хотя на практике мало кто этим пользуется...
                                            • UFO just landed and posted this here
                                                0
                                                ну... я же про принципиальное отличие, а не про плюсы/минусы/проблемы ;)
                                                • UFO just landed and posted this here
                                              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>

                                                    Насчет вызова разных таблиц - напишу в следующей статье. Там много тонкостей.
                                                    • UFO just landed and posted this here
                                                +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 это уже поддерживается.
                                                      • UFO just landed and posted this here
                                                          0
                                                          насчет node() я писал немного выше - я не утверждаю, что так и надо. Просто мне пока так удобнее читать: выбираем корневой узел.

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

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

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

                                                                  не в тему:
                                                                  когда уже Хабр будет код подсвечивать и форматировать, а?
                                                                    0
                                                                    Надо подключить парсер посмотреть профиль Spearance
                                                                    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;="
                                                                                0
                                                                                спасиб
                                                                              –1
                                                                              XML:



                                                                              1
                                                                              2
                                                                              3


                                                                              XSLT:




















                                                                              В браузере открывать XML, XSLT-шный файл обозвать transform.xsl и бросить тудаже где файл.xml
                                                                                0
                                                                                Когда код посылаете, нажимайте "предпросмотр", т.к. неясно как его хабр отформатирует.
                                                                                Символы "<" нужно заменить на "&lt;"
                                                                                Сам код лучше обернуть в <code>...</code>.
                                                                                  0
                                                                                  спс, буду знать
                                                                                  –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
                                                                                                  0
                                                                                                  Хех… хабр весь исходный код поел((
                                                                                                  Fade, не дадите ссылку на эту статью на другом сайте, где такой беды не приключилось?)

                                                                                                  Only users with full accounts can post comments. Log in, please.