WebClub - Всероссийский Клуб Веб-разработчиков
WebClub.RU » Советы » Математика и XSLT

Математика и XSLT


Дата публикации: 25-02-2008

Автор:

Боб Дишам

, 5 июля 2001
Оригинал статьи:

http://www.xml.com/


Перевод:

B.Ярошевич

, 1 ноября 2001

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

<numbers>
  <x>4</x>
  <y>3.2</y>
  <z>11</z>
</numbers>

В каждой строке от A до N этой таблицы стилей проводятся (или пытаются) различные вычисления. Эти вычисления проводятся над числами из документа выше и над некоторыми другими, что жестко заданы в таблице стилей или получены при помощи функций, возвращающих числа.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="numbers">
  A. 4 + 3.2        = <xsl:value-of select="x + y"/>
  B. 3.2 - 4        = <xsl:value-of select="y - x"/>
  C. 4 * 3.2        = <xsl:value-of select="x * y"/>
  D. 11/3.2         = <xsl:value-of select="z div y"/>
  E. 4 + 3.2 * 11   = <xsl:value-of select="x+y*z"/>
  F. (4 + 3.2) * 11 = <xsl:value-of select="(x+y)*z"/>
  G. 11 mod 4       = <xsl:value-of select="z mod x"/>
  H. 4 + 3.2 + 11   = <xsl:value-of select="sum(*)"/>
  I. floor(3.2)     = <xsl:value-of select="floor(y)"/>
  J. ceiling(3.2)   = <xsl:value-of select="ceiling(y)"/>
  K. round(3.2)     = <xsl:value-of select="round(y)"/>
  L. 11 + count(*)  = <xsl:value-of select="11+count(*)"/>
  M. 3.2 + string-length("3.2") = 
     <xsl:value-of select="y + string-length(y)"/>
  N. 11 + "hello"     = <xsl:value-of select="z + 'hello'"/>
</xsl:template>
</xsl:stylesheet>

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

  A. 4 + 3.2        = 7.2
  B. 3.2 - 4        = -0.8
  C. 4 * 3.2        = 12.8
  D. 11/3.2         = 3.4375
  E. 4 + 3.2 * 11   = 39.2
  F. (4 + 3.2) * 11 = 79.2
  G. 11 mod 4       = 3
  H. 4 + 3.2 + 11   = 18.2
  I. floor(3.2)     = 3
  J. ceiling(3.2)   = 4
  K. round(3.2)     = 3
  L. 11 + count(*)  = 14
  M. 3.2 + string-length("3.2") = 
     6.2
  N. 11 + "hello"     = NaN

Таблица стилей состоит из одного шаблона, который применяется к элементу исходного дерева numbers. Сам шаблон в свою очередь состоит из набора команд xsl:value-of, в которых атрибуты select используют значения элементов x, y, и z, дочерних по отношению к numbers, для выполнения различных математических операций. В математических выражениях, подобным этим, можно использовать полную мощь XPath для указания, с каким элементом или атрибутом проводить вычисления, однако наша таблица стилей больше предназначена для демонстрации широты доступных математических операций, а не для того, чтобы показать, как с использованием причудливых выражений XPath работать, например, с элементами и атрибутами из четных частей документа.

В строке A шаблона складываются значение x (4) и значение y (3.2) и результат их суммирования, 7.2, помещается в результирующее дерево. Это довольно просто, но таким образом видно, что мы не ограничены целыми числами в математике таблиц стилей.

В строке B мы из 3.2 вычитаем 4, что дает -0.8. Отрицательные числа не должны представлять какие-либо трудности для XSLT-процессоров.

Предупреждение

При работе с некоторыми XSLT-процессорами использование десятичных чисел может дать небольшую ошибку. Например, "3.2 - 4" из нашего примера может дать "-.7999999999999998" для некоторых процессоров. И вроде ошибка в .0000000000000002 невелика, тем не менее это показывает, что математика не является сильной стороной XSLT.

В строке C мы перемножаем 4 и 3.2, используя звездочку (*) в качестве оператор умножения. В результате получается 12.8.

В строке D проводится деление значение элемента z, (11), на 3.2, что демонстрирует возможность XSLT-процессора выполнять деление с плавающей точкой. Хотя в большинстве языков программирования традиционно используется символ слэша (/) для обозначения математического деления, в XPath уже зарезервирован этот символ для разделения шагов в пути выборки (location path) XPath (например, wine/vintage для представления элемента vintage, дочернего по отношению к элементу wine). Поэтому, XPath и XSLT используют для обозначения деления строку "div".

В строках E и F показывается, что круглые скобки так же влияют на очередность выполнения операторов, как и в нормальной математической нотации: без них умножение выполняется перед сложением, таким образом 4 + 3.2 * 11 = 4 + 35.2. С круглыми же скобками вокруг "4+3.2" это сложение выполняется первым, и теперь (4 + 3.2) * 11 = 7.2 * 11.

В строке G демонстрируется действие оператора mod, который возвращает остаток при делении первого терма на второй. Пример показывает, что 11 mod 4 равен 3, так как 4 входит в 11 дважды плюс 3 в остатке. Этот оператор удобно применять для проверки делится ли одно число на другое - надо только проверить, равен ли остаток нулю.

В строке H демонстрируется функция sum(). Имея список узлов в качестве аргумента, она возвращает сумму всех чисел в этом списке. Звездочка (*) обозначает "все дочерние элементы контекстного узла", то есть в нашем примере элементы x, y и z, дочерние по отношению к элементу numbers.

В строки I и J иллюстрируют применения функций floor() и ceiling(). Если их применить к целым числам, то они их и вернут. Если же применить floor() к числу, неявляющимуся целым, то она вернет наибольшее целое меньшее аргумента. В нашем примере, floor(3.2) есть 3. В тоже время функция ceiling возвращает наименьшее целое число, которое больше, чем число в аргументе; в нашем примере ceiling(3.2) равно 4.

Функция round() в строке K округляет число, возвращая ближайшее к нему целое число. Так, когда на вход ей подается 3.2, она возвращает 3; если же на входе 3.5 или 3.6, то результатом будет 4.

Строка L содержит другую XPath-функцию, count(), которая возвращает количество узлов в множестве, указанном в ее аргументе. XPath предоставляет несколько функций, которые не являются чисто математическими, но тем не менее возвращают числа и могут использоваться в различных вычислениях: count(), last(), position(), и string-length(). Так, в строке M демонстрируется функция string-length(), возвращающая длину строки.

В строке N демонстрируется, что бывает, когда вы пытаетесь провести какие-либо математические вычисления с чем-либо, что не является числом: при попытке сложить 11 и строку "hello" результатом будет строка "NaN" (сокращение от "Not a Number"). Когда вы берете число из содержания элемента или значения атрибута и используете его вычислений, вы не всегда можете быть уверенным, что это действительно число, таким образом четко определенное поведение XSLT для некорректных случаев упрощает подобную проверку.

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

pi

. Точность результата зависит от значения переменной iterations.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     version="1.0">
<xsl:output method="text"/>
<!-- Вычисляет 'pi'. Основан на алгоритме Лейбница: 
       pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11... откуда
       pi = 4 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11...
-->
<xsl:variable name="iterations" select="30000"/>
<xsl:template name="pi">
  <!-- named template called by main template below -->
  <xsl:param name="i">1</xsl:param>
  <xsl:param name="piValue">0</xsl:param>
  <xsl:choose>
  <!-- Если проведено недостаточное количество итераций,
	  добавить уже вычисленное значение pi к
	  очередному приближению вычислений. -->
  <xsl:when test="$i &lt;= $iterations">
    <xsl:call-template name="pi">
      <xsl:with-param name="i" select="$i + 4"/>
      <xsl:with-param name="piValue" 
           select="$piValue + (4 div $i) - (4 div ($i + 2))"/>
    </xsl:call-template>
  </xsl:when>
  <!-- Если проведено достаточное количество
	  итераций, копировать вычисленное значение
	  в результирующее дерево. -->
  <xsl:otherwise>
   <xsl:value-of select="$piValue"/>
  </xsl:otherwise>
  </xsl:choose>
</xsl:template>
<xsl:template match="/">
  <xsl:call-template name="pi"/>
</xsl:template>
</xsl:stylesheet>

Вычисление основано на рекурсивном применении именованного шаблона. С таким начальным значением iterations таблица стилей выдаст следующий результат:

3.1415259869231935

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

 

 

BBus. Заказ и аренда автобуса недорого для переовзки персонала к месту работы и обратно.
Домен продается

Популярное

Не так давно в сети появился новый сервис, под названием Dead Man Zero. Этот сервис сделал...
Рынок социальных площадок уже давно стал стабильным. Несмотря на то, что время от времени...
Artisteer 4 – единственный в своем роде продукт, позволяющий автоматизировать работу над созданием...
Апрель 2024 (1)
Октябрь 2018 (14)
Февраль 2017 (3)
Январь 2017 (1)
Август 2016 (1)
Май 2016 (2)

Карта сайта: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41

Друзья сайта



Случайная цитата

Неизвестный автор:

"Жизнь – как сидение в интернете: смысла нет, а уходить не хочется."

Опрос

Какой антивирус Вы используете?

Kaspersky Antivirus
NOD32
Norton Antivirus
Dr.Web
Panda
Аvast!
ClamWin
Другой...