ShortXSLT: упрощенный синтаксис для XSLT с операторами вставки, if, else и т. д.

    Библиотека Dklab_ShortXSLT — это система для поддержки упрощенного синтаксиса XSLT для встроенных в PHP классов XSLTProcessor и DOMDocument. Фактически, это компилятор с диалекта XSLT в стандартный XSLT, запускаемый «на лету» и «прозрачно» для вызывающего кода (естественно, имеется возможность кэширования, чтобы компиляция запускалась только в до следующего изменения шаблона). Там, где вы используете XSLT в PHP-скриптах, вы можете подключить ShortXSLT, написав несколько дополнительных строчек кода.

    Стандартный синтаксис XSLT весьма громоздок, что оказывается неудобным при его использовании в Web-программировании. Библиотека позволяет облегчить эту проблему.

    Поддерживаются сокращенные версии для следующих конструкций: вставка значения вне тэгов, вставка языковой константы, вставка sprintf-like константы, if-then-elseif, foreach.

    Пример на ShortXSLT:
    ...
    <xsl:template match="/">
      {if /some/node = 1}
        {#hello}, world! {#my_name_is(/my/name)}.
      {elseif /other/node = /some/node}
        <p>You have {/money} dollars.</p>
      {else}
        {foreach /nodes/*}
          Node {.}<br/>
        {/foreach}
      {/if}
    </xsl:template>
    ...
    


    А вот то же самое, но на чистом XSLT:
    ...
    <xsl:template match="/">
      <xsl:choose>
        <xsl:when test="/some/node = 1">
          <xsl:value-of select="h:const('hello')" />, world! 
          <xsl:value-of select="h:const('my_name_is', /my/name)" />.
        </xsl:when>
        <xsl:when test="/other/node = /some/node">
          <p>You have <xsl:value-of select="/money" /> dollars.</p>
        </xsl:when>
        <xsl:otherwise>
          <xsl:for-each select="/nodes/*">
            Node <xsl:value-of select="." /><br/>
          </xsl:for-each>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>
    ...
    

    ShortXSLT лишь расширяет набор инструкций XSLT. При этом все стандартные конструкции XSLT остаются доступными. Например, вы можете использовать <xsl:value-of select=«node» disable-output-escaping=«yes» /> для вставки «сырого» HTML в результирующий документ (конструкция {node} всегда вставляет «заквоченные» данные).

    Библиотека распространяется по лицензии LGPL и доступна для скачивания на dklab.ru/lib/Dklab_ShortXSLT

    Похожие публикации

    Средняя зарплата в IT

    111 111 ₽/мес.
    Средняя зарплата по всем IT-специализациям на основании 6 788 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 56

      +3
      за каждое использование if, else и foreach в xslt надо отрывать по одной руке.
        +2
        И как реализовать например вывод списка через запятую, но без запятой в конце?
          +1
          Tenshi, а можно хоть как-нибудь аргументировать?

          Ммм, если по-вечер голова работает правильно, то вот вам вариант без логических операторов:
          <xsl:for-each select='node[position() = last() — 1]'>
          <xsl:value-of select='.'/>, 
          </xsl:for-each>
          <xsl:value-of select='node[position() = last()]'/>.
            0
            Но с for-each ;)
              0
              Можно все это разнести по двум разным шаблонам с вызовом оных. Лень писать код, но вы надеюсь меня поняли.
                +2
                Да, понял ;) Я не спорю, сделать без if и foreach можно, но зачем? Это всего лишь инструмент, где-то его удобнее применить, где-то его можно применить, но получится например код в котором не очень просто разобраться другому человеку и при этом есть более рациональный способ. Я не вижу объективных причин, что бы полностью отказаться от этих конструкций в xslt.
                  –1
                  в портянке на 1000 строк разобраться не проще…
                    0
                    Дык вы что-нибудь предложите, а то все критикуете, критикуете ;)
          • НЛО прилетело и опубликовало эту надпись здесь
              0
              XSLT 2.0 это конечно хорошо, но к сожалению libxslt его пока не поддерживает. И я не знаю ни одного свободного XSLT 2.0 процессора, написанного на C/C++. А тащить Java только ради XSLT процессора не хочется. Python, PHP, Perl etc в принципе тоже подошли бы, хотя с точки зрения потребления ресурсов C/C++ предпочтительнее. А так способ конечно хороший, но для простых списков, когда нужно вставить элементы просто текстом, хотя тут не уверен, с XSLT 2.0 пока особо не знакомился.
              0
              [apply-templates select="." mode=«separator»/]



              [template match="*" mode=«separator»],[/template]
              [template match="*[ position() = last() ]" mode=«separator»/]
                +1
                Против:
                <xsl:if test="not (position()=last())">, </xsl:if>
                

                Т.е. плодить лишние сущности это нормально, а использовать if нет? На мой взгляд тут как раз показан пример XSLT который при разрастании будет трудно читать. А если надо список не просто в виде текста изобразить, например в виде ссылок, будем <a href="..."> дублировать дважды? Или может еще один шаблон создадим? Вот за такое действительно руки отрывать надо.
                  0
                  Не сразу понял все нюансы предложенного метода, в общем то он не так уж плох, в случае если таких списков несколько, но для одного по моему перебор.
                    0
                    ага, единственный список через запятую на весь сайт =)
              0
              вы правы, ведь xslt своего рода функциональный язык. но не так категорично, чтоб прям отрывать руки
                0
                Вы хотели сказать декларативный. Ну и чем при таком раскладе нам мешает if-else-foreach?
                  +2
                  да ничем не мешает! более того, если бы там подобные конструкции были абсолютно не нужны, то их бы там не было, но они то есть — значит нужны.

                  товарищ Tenshi наверняка имел в виду те случаи, когда на самом деле надо отрывать руки — весь шаблон, это один темплейт, в котором куча xsl:if и xsl:foreach, в котором перебирается все дерево. да, такой шаблон работает, но выглядит жутко и труден для восприятия при редактировании, если темплейт на много строк (а он скорее всего при таком раскаладе будет на очень много строк).

                  подобный шаблон с одним мега-темплейтом лучше разбить на несколько темплейтов, тогда foreach-ей и if-ов станет заметно меньше, а код будет более «тру»

                  такой «не тру» способ юзанья xslt часто встречается у начинающих. я сам был таким и сам писал такие мега-темплейты, а потом я увидел как «тру» и мне стало стыдно за свой код.

                  подобная аналогия: вы можете реализовать любой алгоритм в си-подобных языках, используя if и while, но это же можно сделать более элегантно с for, foreach, switch и т.д.
                    0
                    При таком раскладе вы конечно совершенно правы;)
                      +1
                      а библиотечка-то как раз такому мега-темплейтингу и потакает =)

                      наверняка она удобна только когда используем что-то типа XSL-FO, а в штате программеров нет грамотного xslt-шника. php кодеру с таким синтаксисом разобраться просто и быстро. результат получится дешевый и сердитый — не более чем заглушка в большом проекте, где xsl присутствует незначительно. использовать шаблонизатор на такой либе для всего проекта = тогда нафига вообще xslt ?!

                      это не камень в огород димы котерова, просто очень бесят люди, которые трясутся над «разделением бизнес-логики и логики представления» вплоть до того, что внедряют xslt только потому что там нельзя подконнектиться бд, записать данные в сессию и т.д.

                      скажу по секрету: видел мега-темплейты в шаблонах отрисовки админки одной известной коммерческой цмс. так что тех, кто не может учуять код, который «smell», очень много =)
                        –1
                        Верно, хотя, имхо, XSLT синтаксис предельно прост и спокойно читается «на лету». А вот проблему с его громоздкостью можно проще решить назначением десятка code-templates в реакторе.
                          0
                          Хотелось бы заметить, что первые два абзаца предыдущего поста необходимо снабдить словом ИМХО, т.к. они весьма далеки от действительности.

                          Также (ИМХО) «мега-темплейты» не имеют отношения к конструкциям if-else и foreach, а имеют отношение, главным образом, к неопытности XSLT-писателя.
                            0
                            … я имел в виду «первые два абзаца РОДИТЕЛЬСКОГО поста»
                              0
                              здравствуйте, дима! я интонацию «ИМХО» выразил словом «наверняка».

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

                              моя позиция в этом топике такова, потому что боюсь, что новичок найдет вашу либу, начнет ее использовать и не будет знать как написать чистый xslt. почему не будет знать про остальные прелести данной технологии? да потому что то, что вы реализовали, покрывает потребности 95% php программистов, подыскивающих свежий/модный/мощный (нужное выбрать) шаблонизатор.

                              я знаю, что мое мнение спорное. я знаю, что даже обертки над обертками над обертками зачастую бывают удобны и экономят время (=деньги), но тут-то уж извольте. xslt не так сложен и заумен, чтобы относиться к нему, как чему-то, что нуждается в обертке.
                                0
                                Хм. Будет знать {some/node}, но не поймет <xsl:value-of select=«some/node» />? Или узнает {if something}, но не додумается до <xsl:choose><xsl:when test=«something»>? Конечно, я понимаю, что новички разные бывают, но чтоб такое не понять, нужно очень сильно постараться…

                                Про 95% — мне кажется, это сильное преувеличение. Чтобы использовать XSLT в качестве веб-шаблонизатора, нужно как минимум еще применять xsl:template, xsl:call-template (или apply-templates, но это реже) и xsl:import. Без них никакого шаблонизатора не сделать, а чтобы их применять, нужно очень хорошо себе представлять, как работает xslt.
                                  0
                                  бывают и не такие =)

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

                                  за предыдущий параграф простите, это наболело

                                  знать про xsl:template не обязательно — эта конструкция копипастится и кочует из файла в файл в качестве «эта фигня идет в самом начале». apply-templates — аналогично воспринимается как «типа вызов функции». я рассказываю свой личный опыт и опыт моего товарища, с которым мы вместе по приколу начинали разбираться с xslt весной 2006 года. xsl:template почти всегда был один в каждом файле шаблона, и match был всегда один и тот же. apply-templates мы использовали только для того, чтобы вытащить из узла его контент с тегами через xsl:copy-of select='child::node()' — подсмотрено на каком-то форуме. все остальное, что мы использовали — есть у вас в либе: красивое, понятное и простое решение проблем прямо на блюдечке.

                                  мы не видели коренного различия xslt от того же смарти или спагетти кода на php. я одной извилиной понимал, что что-то тут не так, и где-то есть та главная фишка из-за которой программисты мирятся с таким «ужасным» синтаксисом. только через пол года узрел эту фишку. а с такой либой у меня бы и не возникло подобной мысли. и уверен у многих бы не возникло.

                                  вот, мини-мемуары получились =)
                                    0
                                    можно было б и вообще без xsl:template =)
                                    www.citforum.ru/internet/xslt/xslt02.shtml#result-element-stylesheet
                                      0
                                      В libxslt это пока не поддерживается. Кстати, интересно было бы узнать, с какой XSLT-библиотекой вы работали?
                                        0
                                        libxslt, msxml, transformiix
                                          0
                                          тот libxslt, что идёт вместе с сафари и хромым — вполне себе поддерживает.
                      0
                      Эм… Ну за if и else я еще могу представить. А где взять третью руку для foreach?
                        0
                        Почему? Имхо, шаблонизатор должен уметь жонглировать данными как угодно. Если у вас циклы и условия, связанные с отображением, в коде программы, а не в шаблонах, то я бы за это как раз руки отрывал :)
                          0
                          а людям, которые не видят разницы между отображением и шаблонами — нужно отрывать яйца. чтобы не размножались…
                        –5
                        А к чему это поделие? котеров очередной раз испражнился?
                        Типа — библиотека для совсем-совсем дибилов?
                          –1
                          я предположил
                            –1
                            блин… ссылку съел типограф. #comment_1461867 выше
                          +1
                          да, и с такой локализацией слишком много мороки: [xsl:value-of select=«h:const('my_name_is', /my/name)» /]
                          локали лучше выносить в отдельный слой вставляя на этапе «логики отображения» лишь: [loc:my_name_is p:name="{ /my /name }" /]
                            0
                            как, собственно, и саму логику лучше выносить в отдельный от отображения слой. причём логику риальна удобней реализовывать на пхп, чем на хслт.
                            • НЛО прилетело и опубликовало эту надпись здесь
                                0
                                не-не-не, дэвид блейн, нинада писать программы на языке запросов! =)
                                • НЛО прилетело и опубликовало эту надпись здесь
                                    0
                                    нет, клиент посылает комманду серверу, сервер что-то там делает и формирует ответ в котором информирует клиента о результатах выполнения комманды. а комманды бывают разные: get, post, head, push, pop, feed, spit, ping, switch…
                                    • НЛО прилетело и опубликовало эту надпись здесь
                                        0
                                        серверное приложение — это не тупой транслятор из http в sql(xquery) и обратно.
                                        например комманда «скачай такой-то файл с удалённого сервера попротоколу sftp, распарсь его в соответствии с правилами yml и сохрани на локальный диск в формате xml» ну никак не укладывается в синтаксис xquery — тут нужен полноценный язык программирования с кучей разнообразных либ.
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                            0
                                            «логику лучше на XQuery реализовывать»
                                            «ява-функции… цеплять»
                                            чтд
                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                0
                                                у меня проекты разные, требования тоже, так что цеплять придётся везде и по многу…
                                                • НЛО прилетело и опубликовало эту надпись здесь
                              0
                              Да, но в этом случае мы теряем в производительности: придется результат XSLT-преобразования прогонять через еще одно XSLT-преобразование для замены локализованных вставок. Кроме того, для улучшения производительности иногда имеет смысл автоматически «вкомпилить» строковые значения в исходный XSLT еще до преобразования, т.е. заменить {#hello} на «Привет». Тогда не будет тратиться время на вызов функции вида h:const(). Такую замену можно сделать при помощи препроцессор Dklab_DOMDocument, на котором и написан, собственно, ShortXSLT.
                                0
                                не думаю, что сотни вызовов пхп-шной функции быстрее, чем одно простое хслт-преобразование.
                                ну и прекомпиляцию локалей в хслт тоже можно сделать, но куда больше толку будет от поднятия отдельного демона-трансформера, который бы не парсил хслт каждый раз заново и тем самым пренепременно достиг бы околосветовых скоростей даже с несколькими проходами.
                              0
                              Надо было идти дальше и закрывающий тэг сделать более простым: {/}
                              Так же нужно проверить, будет ли ShortXSLT ошибочно обрабатывать параметры в атрибутах <a href="{link}">

                              А вообще, мне не нравится эта идея, лучше использовать более навороченный текстовый редактор, позволяющий вводить XSLT тэги быстро, например набрал choose<Tab> и получил <choose><when test="_"></when><otherwise></otherwise></choose>, будет быстрее, и не нужно тратить время на компиляцию из ShortXSLT в XSLT.
                              • НЛО прилетело и опубликовало эту надпись здесь
                                  0
                                  Хороший редактор помогает быстро набирать код, но, к сожалению, плохо помогает потом быстро его читать и просматривать.
                                  +1
                                  Это уже не XSLT получается, а извращение. XSLT-процессор писать на PHP — бред полнейший. XSLT — кроссплатформенное решение. Следующим шагом вы должны написать XSLT-процессор на Javascript, чтобы ваши теги обрабатывались при парсинге XSLT из браузера. Извините, но из конфетки сделали говно!
                                    0
                                    Вы совершенно правы, это правда был бы бред. Именно поэтому это не «XSLT-процессор, написанный на PHP», а «система для поддержки упрощенного синтаксиса XSLT для встроенных в PHP-классов XSLTProcessor и DOMDocument». Поправил в посте, чтобы не было недопониманий.
                                    0
                                    smarty4xslt? закапывайте обратно.

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

                                    Самое читаемое