Pull to refresh

Мелочи в XSLT 1.0

Reading time6 min
Views3.1K
Реализация функций replace(), uppercase(), lowercase()


Пример реализации функции replace в XSLT 1.0.
Сканируем text на совпадение с патэрном target, затем замещаем совпавший текст строкой value и возвращаем результирующую строку.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" encoding="utf-8" indent="yes"/>

  <xsl:template match="/">
    <xsl:variable name="string">Stop war! Make peace!</xsl:variable>

    <xsl:call-template name="Replace">
      <xsl:with-param name="string" select="$string"/>
      <xsl:with-param name="target" select="'peace'"/>
      <xsl:with-param name="value" select="'love'"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="Replace">
    <xsl:param name="string"/>
    <xsl:param name="target"/>
    <xsl:param name="value"/>
    <xsl:choose>
      <xsl:when test="contains( $string, $target)">
        <xsl:call-template name="Replace">
          <xsl:with-param name="string" select="concat(substring-before($string, $target), $value, substring-after($string, $target))"/>
          <xsl:with-param name="target" select="$target"/>
          <xsl:with-param name="value" select="$value"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$string"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  
</xsl:stylesheet>

* This source code was highlighted with Source Code Highlighter.

В результате вместо
Stop war! Make peace!
будет Stop war! Make love!

Пример реализации функции uppercase в XSLT 1.0.
Сканируем text на совпадение с патэрном value, затем замещаем совпавший текст и возвращаем результирующую строку.
В данной реализации предполагается смена регистра целого слова.
При совпадении в text искомого текста value, проверяем не является ли найденое частью слова и если нет, то проводим замену. Метод перевода в нижний регистр аналогичен методу перевода в верхний.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" encoding="utf-8" indent="yes"/>

  <xsl:variable name="lower">abcdefghijklmnopqrstuvwxyz</xsl:variable>
  <xsl:variable name="upper">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>

  <xsl:template match="/">
    <xsl:variable name="text">Правильно построенный (Well-formed). Правильно построенный документ соответствует всем общим правилам синтаксиса xml, применимым к любому xml-документу</xsl:variable>
    
    <xsl:call-template name="Uppercase">
      <xsl:with-param name="text" select="$text"/>
      <xsl:with-param name="value" select="'xml'"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="Uppercase">
    <xsl:param name="text"/>
    <xsl:param name="value"/>
    <xsl:choose>
      <xsl:when test="contains($text, $value)">
        <xsl:variable name="symbolBefore" select="substring(substring-before($text, $value), string-length(substring-before($text, $value)) )"/>
        <xsl:variable name="symbolAfter" select="substring(substring-after($text, $value), 1,1)"/>

        <xsl:choose>
          <xsl:when test="not(contains($lower,$symbolBefore) and contains($lower,$symbolAfter))">
            <xsl:call-template name="Uppercase">
              <xsl:with-param name="text" select="concat(substring-before($text, $value),translate($value,$lower,$upper),substring-after($text, $value))"/>
              <xsl:with-param name="value" select="$value"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$text"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>


* This source code was highlighted with Source Code Highlighter.

В результате все 'xml' трансформируются в 'XML'.

Для придания большей функциональности (генерации случайного числа, работы с датами, расширенные операции со строками и регулярными выражениями, большим количеством математических операций) можно использовать расширения, например
EXSLT (Extensions to Extensible Stylesheet Language Transformations).
Например, для генерации рандомного числа, согласно XSLT 1.0 Pocket Reference, будет следующий код:

<xsl:stylesheet version="1.0"
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
          xmlns:random="http://exslt.org/random"
          exclude-result-prefixes="random">
        <xsl:output indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="/">
    <xsl:copy-of select="random:random-sequence(3)"/>
  </xsl:template>    
    
</xsl:stylesheet>

* This source code was highlighted with Source Code Highlighter.

Результатом будут три числа от 0 до 1.

UPD.
Пример вывод минимального/максимального значения (удивительно, но в упомянутой в комментах книге такого простого примера нет)
Допустим есть простой xml
<Price>
  <Number>15</Number>
  <Number>7</Number>
  <Number>8</Number>
  <Number>11</Number>
  <Number>3</Number>
  <Number>42</Number>
  <Number>21</Number>
  <Number>6</Number>
</Price>
* This source code was highlighted with Source Code Highlighter.

сразу переходим к решению (в случае нахождения максимального)
<xsl:value-of select="Price/Number[not(following-sibling::Number > self::Number)]"/>
* This source code was highlighted with Source Code Highlighter.
знак > хабр преобразил

42 — ответ на ВСЁ :)
Tags:
Hubs:
Total votes 10: ↑9 and ↓1+8
Comments12

Articles