Добавляем сахар в XSLT

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

    <p x:each="item" x:if-attr="position() mod 2" x:attr-class="'odd'" xmlns:x="xslt-sugar">
      <span class="date" x:value="date"/>
      <xsl:value-of select="title"/>
      <x:block x:if="description" x:value="concat(' ', description)" x:doe="yes"/>
    </p>
    

    После преобразования этого кода получим обычный XSLT:
    <xsl:for-each select="item">
      <p>
        <xsl:if test="position() mod 2">
          <xsl:attribute name="class"><xsl:value-of select="'odd'"/></xsl:attribute>
        </xsl:if>
        <span class="date"><xsl:value-of select="date"/></span>
        <xsl:value-of select="title"/>
        <xsl:if test="description">
            <xsl:value-of select="concat(' ', description)" disable-output-escaping="yes"/>
        </xsl:if>
      </p>
    </xsl:for-each>
    
    Обратите внимание, что параметры x:attr-name="val" выводятся через <xsl:value-of select="val"/>, поэтому строковые параметры заключайте в кавычки, как это сделано в примере.

    Собственно сам шаблон xslsugar.xslt
    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:x="xslt-sugar" version="1.0">
    
    <xsl:output method="xml" indent="yes" encoding="utf-8"/>
    
    <xsl:template match="*|@*|text()|processing-instruction()|comment()">
      <xsl:copy>
        <xsl:apply-templates select="*|@*|text()|processing-instruction()|comment()"/>
      </xsl:copy>
    </xsl:template>
    
    <xsl:template match="x:*|@x:*"/>
    
    <xsl:template match="x:block">
      <xsl:apply-templates select="*|@*|text()|processing-instruction()|comment()"/>
    </xsl:template>
    
    <xsl:template match="@x:value">
      <xsl:element name="xsl:value-of" namespace="http://www.w3.org/1999/XSL/Transform">
        <xsl:attribute name="select"><xsl:value-of select="."/></xsl:attribute>
        <xsl:if test="../@x:doe"><xsl:attribute name="disable-output-escaping"><xsl:value-of select="../@x:doe"/></xsl:attribute></xsl:if>
      </xsl:element>
    </xsl:template>
    
    <xsl:template match="*[@x:if]">
      <xsl:element name="xsl:if" namespace="http://www.w3.org/1999/XSL/Transform">
        <xsl:attribute name="test"><xsl:value-of select="@x:if"/></xsl:attribute>
        <xsl:apply-templates select="." mode="element"/>
      </xsl:element>
    </xsl:template>
    
    <xsl:template match="*[@x:each]">
      <xsl:element name="xsl:for-each" namespace="http://www.w3.org/1999/XSL/Transform">
        <xsl:attribute name="select"><xsl:value-of select="@x:each"/></xsl:attribute>
        <xsl:apply-templates select="." mode="element"/>
      </xsl:element>
    </xsl:template>
    
    <xsl:template match="@x:if-attr">
      <xsl:element name="xsl:if" namespace="http://www.w3.org/1999/XSL/Transform">
        <xsl:attribute name="test"><xsl:value-of select="."/></xsl:attribute>
        <xsl:for-each select="../@x:*[starts-with(local-name(), 'attr-')]">
          <xsl:element name="xsl:attribute" namespace="http://www.w3.org/1999/XSL/Transform">
            <xsl:attribute name="name"><xsl:value-of select="substring(local-name(), 6)"/></xsl:attribute>
            <xsl:element name="xsl:value-of" namespace="http://www.w3.org/1999/XSL/Transform">
              <xsl:attribute name="select"><xsl:value-of select="."/></xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:for-each>
      </xsl:element>
    </xsl:template>
    
    <xsl:template match="*" mode="element">
      <xsl:copy>
        <xsl:apply-templates select="*|@*|text()|processing-instruction()|comment()"/>
      </xsl:copy>
    </xsl:template>
    
    <xsl:template match="x:block" mode="element">
      <xsl:apply-templates select="*|@*|text()|processing-instruction()|comment()"/>
    </xsl:template>
    
    </xsl:stylesheet>
    


    Каким образом это использовать и как расширять возможности решайте сами, здесь лишь идея.

    П.С.: Скрипт для преобразования вашего Sugar XSLT:
    #!/bin/sh
    cp $1 $1.bak
    xsltproc -o $1 xslsugar.xslt $1
    
    В Windows это можно сделать через:
    msxsl.exe -o template.xslt template.xslt xslsugar.xslt
    (не пробовал)

    П.П.С.: Если захотите использовать уже имеющийся xmlns:xsl, что не правильно, но удобно, то просто замените в xslsugar.xslt пространство имен xmlns:x="xslt-sugar" на xmlns:x="http://www.w3.org/1999/XSL/Transform" и уберите x:* из пустого шаблона: <xsl:template match="@x:*"/>, в итоге сможете писать без дополнительного пространства имен: <p xsl:each="item">

    Следующую версию, и дальнейшее развитие смотрите на code.google.com/p/xslt-sugar
    • +13
    • 3,4k
    • 8
    Поделиться публикацией

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

    Комментарии 8
      +7
      Xslt для xslt — мне кажется это явный перебор, не вижу смысла, ну кроме академического разве что ли.
        0
        Ну почему же? Это решение вполне конкретной задачи — упростить ручной набор XSL-кода.
          0
          По-сути это уже XML для XSLT. Получается просто пер-блочное преобразование дополнительно. Хотя мне хватает и EXSLT для упрощения жизни (отчасти).
            +1
            Когда будете писать свой XSLT шаблон, попробуйте использовать это решение, и поймете, есть ли практический смысл. Если не понравится, ваша работа не пропадет, можно будет из консоли мгновенно преобразовать в обычный XSLT, а исходный код удалить.

            Вполне возможно написание и обратного преобразования.
            0
            Почему это назвали «сахар»?
              0
              От «синтаксический сахар», первое что в голову пришло, нужно было как-то пространство имен назвать.
              +1
              Меня сильно раздражает разнообразие php-шаблонизаторов — smarty, twig, blitz, tal… В каждой конторке где приходилось работать шаблонизатор свой и самый лучший. Только недокументированный. Во фреймворках и CMS он документированный, но разный и каждый раз приходится садиться и учить, то что и существовать то не должно при наличии кроссплатформенного встроенного в php и рекомендованного w3c XSLT-стандарта.
              Ваш сахар, чем-то мне эту ситуацию напоминает.
                0
                Так он предназначен только для удобства ввода, после того, как шаблон отлажен, из него получаем стандартный XSLT, который уже и поддерживаем дальше.

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

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

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

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