1. Главная
  2. Функции XPath
  3. avg()

avg XPath

Возвращает для заданной последовательности среднее арифметическое всех значений.

Синтаксис

xs:anyAtomicType? avg(xs:anyAtomicType*)

Ввод

Последовательность значений.

Вывод

Среднее арифметическое значений заданной последовательности. Среднее значение может вычисляться для шести типов данных: xs:integer, xs:double, xs:decimal, xs:float, xs:yearMonthDuration и xs:dayTimeDuration.

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

Функция avg() предполагает, что переданная последовательность содержит осмысленные данные; в противном случае процессор XSLT выдает ошибку. Например, при вызове для последовательности (42, 57, 'blue') процессор XSLT, как и следовало ожидать, вернет ошибку.

Несколько замечаний по поводу работы функции avg():

  • Для вычисления среднего значения для последовательности временных промежутков все значения должны относиться к типу xs:dayTimeDurations или xs:yearMonthDurations. Смешанное использование двух типов недопустимо; если вы попытаетесь это сделать, процессор XSLT выдаст ошибку.
  • Если все значения последовательности относятся к типу xs:untypedAtomic, процессор XSLT пытается преобразовать каждое значение к типу xs:double. Если хотя бы одно значение в последовательности не удается преобразовать к xs:double, процессор XSLT выдает ошибку.
  • Наконец, если передать avg() пустую последовательность, функция вернет пустую последовательность. Хотя в этом случае функция не получает никаких полезных данных, процессор XSLT не выдает ошибку.

Описание и примеры

Где определяется

XQuery 1.0 and XPath 2.0 Functions and Operators, раздел 15.4 «Aggregate Functions».

Пример

Таблица стилей для вычисления средних значений нескольких последовательностей:

<?xml version="1.0"?>
<!-- avg.xsl -->
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="text"/>
    <xsl:template match="/">
        <xsl:variable name="seq1" select="(3, 5, 18)"/>
        <xsl:variable name="seq2" select="(3, 5, 48.273, 2.9e3)"/>
        <xsl:variable name="value1" as="xs:integer" select="42"/>
        <xsl:variable name="value2" as="xs:double" select="2718.28E-3"/>
        <xsl:variable name="value3" as="xs:float" select="98.6"/>
        <xsl:variable name="value4" as="xs:decimal" select="2.54"/>
        <xsl:variable name="seq3" select="($value1, $value2, $value3, $value4)"/>
        <xsl:variable name="seq4" select="(xs:yearMonthDuration('P3Y8M'), xs:yearMonthDuration('P4Y2M'), xs:yearMonthDuration('P6Y4M'))"/>
        <xsl:variable name="seq5" select="(xs:dayTimeDuration('P2DT4H23M12.2S'), xs:dayTimeDuration('P3DT8H17M'), xs:dayTimeDuration('P3D'))"/>
        <xsl:text>&#xA;Here are some tests of the avg() function:&#xA;</xsl:text>
        <xsl:text>&#xA; avg(</xsl:text>
        <xsl:value-of select="$seq1" separator=", "/>
        <xsl:text>) = </xsl:text>
        <xsl:value-of select="format-number(avg($seq1), '#.###')"/>
        <xsl:text>&#xA;&#xA; avg(</xsl:text>
        <xsl:value-of select="$seq2" separator=", "/>
        <xsl:text>) = </xsl:text>
        <xsl:value-of select="format-number(avg($seq2), '#.###')"/>
        <xsl:text>&#xA;&#xA; avg(</xsl:text>
        <xsl:value-of select="$seq3" separator=", "/>
        <xsl:text>) = </xsl:text>
        <xsl:value-of select="format-number(avg($seq3), '#.###')"/>
        <xsl:text>&#xA;&#xA; avg(</xsl:text>
        <xsl:value-of select="$seq4" separator=", "/>
        <xsl:text>) = </xsl:text>
        <xsl:value-of select="avg($seq4)"/>
        <xsl:text>&#xA;&#xA; In text, the average of</xsl:text>
        <xsl:for-each select="$seq4">
            <xsl:text>&#xA; </xsl:text>
            <xsl:value-of select="years-from-duration(.)"/>
            <xsl:text> years and </xsl:text>
            <xsl:value-of select="months-from-duration(.)"/>
            <xsl:text> months (</xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>)</xsl:text>
        </xsl:for-each>
        <xsl:text>&#xA; is </xsl:text>
        <xsl:value-of select="years-from-duration(avg($seq4))"/>
        <xsl:text> years and </xsl:text>
        <xsl:value-of select="months-from-duration(avg($seq4))"/>
        <xsl:text> months (</xsl:text>
        <xsl:value-of select="avg($seq4)"/>
        <xsl:text>).</xsl:text>
        <xsl:text>&#xA;&#xA; avg(</xsl:text>
        <xsl:value-of select="$seq5" separator=", "/>
        <xsl:text>) = </xsl:text>
        <xsl:variable name="avg5" select="avg($seq5)"/>
        <xsl:value-of select="$avg5"/>
        <xsl:text>&#xA;&#xA; In text, the average of</xsl:text>
        <xsl:for-each select="$seq5">
            <xsl:text>&#xA; </xsl:text>
            <xsl:value-of select="days-from-duration(.)"/>
            <xsl:text> days, </xsl:text>
            <xsl:value-of select="hours-from-duration(.)"/>
            <xsl:text> hours, </xsl:text>
            <xsl:value-of select="minutes-from-duration(.)"/>
            <xsl:text> minutes and </xsl:text>
            <xsl:value-of select="format-number(seconds-from-duration(.), '#.##')"/>
            <xsl:text> seconds (</xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>)</xsl:text>
        </xsl:for-each>
        <xsl:text>&#xA; is </xsl:text>
        <xsl:value-of select="days-from-duration($avg5)"/>
        <xsl:text> days, </xsl:text>
        <xsl:value-of select="hours-from-duration($avg5)"/>
        <xsl:text> hours, </xsl:text>
        <xsl:value-of select="minutes-from-duration($avg5)"/>
        <xsl:text> minutes and </xsl:text>
        <xsl:value-of select="format-number(seconds-from-duration($avg5), '#.##')"/>
        <xsl:text> seconds.</xsl:text>
    </xsl:template>
</xsl:stylesheet>

Результат:

Here are some tests of the avg() function:
avg(3, 5, 18) = 8.667
avg(3, 5, 48.273, 2900) = 739.068
avg(42, 2.71828, 98.6, 2.54) = 36.465
avg(P3Y8M, P4Y2M, P6Y4M) = P4Y9M
In text, the average of
3 years and 8 months (P3Y8M)
4 years and 2 months (P4Y2M)
6 years and 4 months (P6Y4M)
is 4 years and 9 months (P4Y9M).[2.0] base5uri() 607
avg(P2DT4H23M12.2S, P3DT8H17M, P3D) = P2DT20H13M24.066666S
In text, the average of
2 days, 4 hours, 23 minutes and 12.2 seconds (P2DT4H23M12.2S)
3 days, 8 hours, 17 minutes and 0 seconds (P3DT8H17M)
3 days, 0 hours, 0 minutes and 0 seconds (P3D)
is 2 days, 20 hours, 13 minutes and 24.07 seconds.

Таблица стилей демонстрирует пять разных типов последовательностей. Первая последовательность состоит только из целых чисел, вторая содержит произвольные числа. Все значения первых двух последовательностей могут быть преобразованы в числа, поэтому результат оказывается таким, каким мы и ожидали. Третья последовательность состоит из четырех числовых значений, относящихся к разным числовым типам (xs:integer, xs:decimal, xs:float и xs:double). Последние две последовательности состоят из двух типов временных промежутков. Кроме того, в таблице стилей для форматирования данных используются такие функции, как years-from-duration() и format-number().

С последовательностью (3, 5, '18') функция не работает, потому что одно из значений последовательности представляет собой строку. Хотя строка '18' может быть преобразована в число функцией number(), функция avg() возлагает эту обязанность на нас: она требует, чтобы все литералы в последовательности были числами или временными промежутками. Впрочем, если последовательность содержит нетипизованные данные (например, узлы, прочитанные из документа, не использующего схему), процессор XSLT пытается преобразовать все эти значения к типу xs:double. Если хотя бы одно из них не удается преобразовать к типу xs:double, процессор XSLT выдает ошибку.

Последнее замечание: если вы хотите сохранить вычисленное среднее значение в типизованной переменной, тип данных xs:double обеспечивает наибольшую гибкость. Использовать самый ограниченный числовой тип xs:integer определенно не рекомендуется. Например, следующий элемент процессор XSLT обработает без всяких возражений:

<xsl:variable name="avg1" as="xs:integer" select="avg((3, 5, 4))"/>

А в этом случае будет выдана статическая ошибка:

<xsl:variable name="avg2" as="xs:integer" select="avg((3, 5, 18))"/>

Если функция avg() используется для динамического задания значения целочисленной переменной, процессор XSLT выдаст ошибку в том случае, если возвращаемое значение не относится к типу xs:integer. Чтобы вызов функции работал, результат необходимо преобразовать к xs:integer:

<xsl:variable name="avg2" as="xs:integer" select="xs:integer(avg((3, 5, 18)))"/>