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

в 3:04, , рубрики: 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"/>, поэтому строковые параметры заключайте в кавычки, как это сделано в примере.

Собственно сам шаблон:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:x="xslt-sugar">

<xsl:output method="xml" indent="yes"/>

<xsl:template match="*|@*|text()|processing-instruction()">
  <xsl:copy>
    <xsl:apply-templates select="*|@*|text()|processing-instruction()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="@x:*"/>

<xsl:template match="x:block">
  <xsl:apply-templates select="*|@*|text()|processing-instruction()"/>
</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="@x:*" mode="element"/>

<xsl:template match="*|@*|text()|processing-instruction()" mode="element">
  <xsl:copy>
    <xsl:apply-templates select="*|@*|text()|processing-instruction()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="x:block" mode="element">
  <xsl:apply-templates select="*|@*|text()|processing-instruction()"/>
</xsl:template>

</xsl:stylesheet>

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

Автор: ibnteo

Поделиться

* - обязательные к заполнению поля