12 Дополнительные функции
В данной главе описываются специфичные для XSLT дополнения к основной библиотеке функций XPath. Некоторые из этих дополнительных функций задействуют также информацию, заданную в стиле элементами верхнего уровня. В главе описаны также и эти элементы.
12.1 Множественные исходные документы
Функция: набор-узлов document(объект, набор-узлов?)
Функция document позволяет получить доступ к иным XML-документам помимо основного исходного документа.
Если функция document имеет ровно один аргумент и этот аргумент является набором узлов, то результатом будет объединение результатов вызова функции document для каждого узла из набора, представленного как аргумент. При этом первым аргументом вызываемой функции будет строковое значение очередного узла, а вторым - набор узлов, в котором этот узел является единственным членом. Если же функция document имеет два аргумента, первый из которых являются набором узлов, то результатом будет объединение результатов вызова функции document для каждого узла из представленного в аргументе набора. При этом первым аргументом вызываемой функции будет строковое значение очередного узла, в качестве второго аргумента будет использован второй аргумент, переданный исходной функции document.
Если первый аргумент функции document не был набором узлов, он преобразуется в строку как при вызове функции string. Полученная строка обрабатывается как ссылка URI, то есть, извлекается ресурс, идентифицируемый этим URI. Полученные таким образом данные обрабатываются как XML документ и в соответствии с моделью данных (см. [3 Модель данных]) строится дерево. Если при извлечении ресурса произошла ошибка, XSLT процессор может сигнализировать о ней. Если он этого не делает, то должен обработать ошибку сам, возвратив пустой набор узлов. Один из возможных типов ошибки извлечения ресурса связан с тем, что XSLT процессор не поддерживает схему, используемую данным URI. XSLT процессор не обязан поддерживать все возможные схемы URI. В документации для XSLT процессора должно быть указано, какие схемы URI поддерживаются этим процессором.
Если ссылка URI не содержит идентификатор фрагмента, возвращается набор узлов, содержащий только корневой узел документа. Если же ссылка URI содержит идентификатор фрагмента, то данная функция возвращает набор узлов из дерева, на которые указывает идентификатор фрагмента из этой ссылки URI. Семантика идентификатора фрагмента зависит от типа среды, полученного при извлечении URI. Если во время обработки идентификатора фрагмента возникла ошибка, XSLT процессор может сигнализировать об ошибке. Если он этого не делает, то должен обработать ошибку сам, вернув пустой набор узлов. Некоторые из возможных ошибок:
Идентификатор фрагмента определяет нечто, чего нельзя представить в виде набора узлов XSLT (например, диапазон символов в текстовом узле).
XSLT процессор не поддерживает идентификаторы фрагмента для типа среды, соответствующего полученному результату. XSLT процессор не обязан поддерживать все типы среды, которые могут существовать. В документации к XSLT процессору должно быть указано, для каких типов сред процессор поддерживает идентификаторы фрагментов.
Данные, полученные в результате извлечения, обрабатываются как XML документ независимо от типа среды у результата извлечения. Если типом среды верхнего уровня является text
, то он обрабатывается точно так же, как если бы тип среды был text/xml
. В противном случае обработка производится так, как если бы тип среды был application/xml
.
Замечание: Поскольку для верхнего уровня нет типа среды xml
, данные с иным типом среды, чем text/xml
или application/xml
действительно могут быть XML.
Ссылка URI может быть относительной. Из набора узлов, представленного во втором аргументе, берется узел, который первым встретится в документе, и его базовый URI (см. [3.2 Базовый URI]) используется для преобразования относительных URI в абсолютные. Если второй аргумент опущен, то по умолчанию используется тот узел из стиля, который содержит выражение, включающее рассматриваемый вызов функции document. Заметим, что ссылка URI нулевой длины является ссылкой на документ, относительно которого эта ссылка URI разрешается. Таким образом, document("")
ссылается на корневой узел данного стиля, а представление стиля в виде дерева в точности такое же как если бы в качестве исходного документа был взят XML документ, изначально содержащий этот стиль.
Если два документа идентифицируются одним и тем же URI, то они обрабатываются как один и тот же документ. Для сравнения используется абсолютный URI, к каковому приводится любой относительный URI, не содержащий каких-либо идентификаторов фрагментов. Два корневых узла обрабатываются как один и тот же узел, если оба взяты из одного и того же документа. Таким образом, следующее выражение всегда будет давать true:
generate-id(document("foo.xml"))=generate-id(document("foo.xml"))
Функция document дает возможность держать в одном наборе узлов узлы сразу из нескольких документов. Для такого набора узлов относительный порядок следования двух узлов, взятых из одного и того же документа - это обычный порядок следования в документе, заданный в XPath [XPath]. Относительный порядок следования двух узлов из различных документов определяется тем, как реализовано упорядочение документов, содержащих эти узлы. Помимо согласованности (для одного и того же набора документов реализация всегда должна давать один и тот же порядок следования) каких-либо иных ограничений на реализацию упорядочения документов нет.
12.2 Ключи
Ключи дают возможность работать с документами, имеющими неявную структуру перекрестных ссылок. В XML атрибуты типа ID
, IDREF
и IDREFS
создают механизм, позволяющий делать в документах XML перекрестные ссылки явными. В XSLT этот механизм реализуется с помощью функции id из XPath. Однако этот механизм имеет ряд ограничений:
Атрибуты ID должны быть декларированы в качестве таковых в DTD. Если атрибут ID декларирован в качестве такового лишь во внешнем наборе DTD, то и распознаваться как ID атрибут он будет только тогда, когда процессор XML прочтет этот внешний набор DTD. Однако спецификация XML вовсе не обязует XML процессоры читать этот внешний DTD, а потому процессоры вполне могут этого не делать, особенно если для документа было декларировано standalone="yes"
.
Документ может иметь только один набор уникальных ID. Не может быть несколько независимых наборов уникальных атрибутов ID.
ID элемента может быть задано лишь в атрибуте. Он не может быть задан ни содержимым элемента, ни элементом, являющимся непосредственным потомком.
ID должен быть именем XML. Например, он не может содержать пробелов.
Элемент может содержать не более одного ID.
Любой конкретный ID может принадлежать только одному элементу.
Из-за этих ограничений документы XML иногда имеют структуру перекрестных ссылок, которая не была явно декларирована атрибутами ID/IDREF/IDREFS.
Ключ определяется тремя параметрами:
узлом, которому принадлежит этот ключ
названием ключа (расширенное имя)
значением ключа (строка)
Набор ключей для каждого документа декларируется в стиле с помощью элемента xsl:key
. Если в данном наборе ключей есть член с узлом x, названием y и значением z, то мы говорим, что узел x имеет ключ с названием y и значением z.
Таким образом, ключ - это такой тип обобщенного ID, на который не распространяются ограничения, принятые для ID в XML:
Ключи декларируются в стиле с помощью элементов xsl:key
.
Ключи имеют как название, так и значение. Каждое название ключа можно рассматривать как отдельное, независимое пространство идентификаторов.
Для элемента значение именованного ключа можно указать в любом удобном месте, например, в содержимом самого элемента, в атрибуте или элементе, являющемся непосредственным потомком. Место, где следует искать значение конкретного именованного ключа, задается выражением XPath.
Значением ключа может быть произвольная строка и это не обязательно должно быть имя.
В документе может быть несколько ключей, относящихся к одному и тому же узлу и имеющих одно и то же название, но с различными значениями ключа.
В документе может быть несколько ключей, имеющих одно и то же название ключа, одно и то же значение, но относящихся к различным узлам.
<!-- Category:
top-level-element -->
<xsl:key
name =
qname
match = pattern
use = expression />
Чтобы декларировать ключи, используется элемент xsl:key
. Название создаваемого ключа задает атрибут name
. Значением атрибута name
является QName, которое приводится к расширенному имени как было описано в главе [2.4 Полные имена]. Атрибут match
является шаблоном. Элемент xsl:key
дает информацию о ключах во всех узлах, которые соответствуют шаблону, заданному атрибутом match. Атрибут use
дает выражение, определяющее значение ключа. Для каждого узла, соответствующего шаблону, это выражение вычисляется отдельно. Если результатом вычисления является набор узлов, то для каждого узла в этом наборе считается, что узлы, соответствующие представленному шаблону, имеют ключ с указанным именем, значением которого является строковое значение данного узла из набора. В противном случае, результат вычисления преобразуется в строку, и соответствующий шаблону узел получает ключ с указанным названием и значением, соответствующим этой строке. Таким образом, узел x имеет ключ с названием y и значением z тогда и только тогда, когда имеется элемент xsl:key
, такой что:
x соответствует шаблону, указанному в атрибуте match
данного элемента xsl:key
,
атрибут name
элемента xsl:key
имеет значение, равное y, и
если выражение, заданное атрибутом use
элемента xsl:key
, обрабатывается с текущим узлом x, а в качестве текущего набора узлов используется список, состоящий из одного x, и при этом результатом является объект u, то либо z равно результату преобразования объекта u в строку (как при вызове функции string), либо u - это набор узлов, а z равно строковому значению одного или нескольких узлов из набора u.
Заметим также, что одному узлу может соответствовать несколько элементов xsl:key
. В этом случае будут использованы все совпавшие элементы xsl:key
, даже если они имеют разный приоритет импорта.
Если значение атрибутов use
или match
содержит VariableReference, фиксируется ошибка.
Функция: набор-узлов key(строка, объект)
Функция id играет для ключей ту же роль, что и функция key для идентификаторов ID. Первый аргумент функции указывает имя ключа. Значением данного аргумента должно быть QName, которое приводится к расширеному имени как было описано в главе [2.4 Полные имена]. Если вторым аргументом функции key является список узлов, то результатом вызова будет объединение результатов вызова функции key для строкового значения каждого узла в списке, указанном в аргументе. Если же второй аргумент функции key имеет какой-либо иной тип, то этот аргумент преобразуется в строку, как при вызове функции string. При этом функция возвращает набор узлов из того же документа, где находится узел контекста, значение именованного ключа которых соответствует этой строке.
Например, дана декларация
<xsl:key name="idkey" match="div" use="@id"/>
выражение key("idkey",@ref)
возвратит тот же набор узлов, что и id(@ref)
, при условии, что в исходном XML-документе был декларирован единственный атрибут ID:
<!ATTLIST div id ID #IMPLIED>
а атрибут ref
текущего узла не содержит пробельных символов.
Предположим, что документ, описывающий библиотеку функций, для определения каковых используется элемент prototype
<prototype name="key" return-type="node-set">
<arg type="string"/>
<arg type="object"/>
</prototype>
а чтобы обратиться к названию функции используется элемент function
<function>key</function>
В таком случае представленный стиль может генерировать гиперссылки между указанными ссылками и определениями следующим образом:
<xsl:key name="func" match="prototype" use="@name"/>
<xsl:template match="function">
<b>
<a href="#{generate-id(key('func',.))}">
<xsl:apply-templates/>
</a>
</b>
</xsl:template>
<xsl:template match="prototype">
<p><a name="{generate-id()}">
<b>Function: </b>
...
</a></p>
</xsl:template>
Функция key может использоваться для извлечения ключа из других документов, нежели тот, в котором содержится текущий узел контекста. Предположим, к примеру, что документ содержит библиографические ссылки в формате <bibref>XSLT</bibref>
, а также есть отдельный XML-документ bib.xml
, содержащий библиографическую базу данных с записями в формате:
<entry name="XSLT">...</entry>
В этом случае в стиле можно использовать следующий вариант преобразования элементов bibref
:
<xsl:key name="bib" match="entry" use="@name"/>
<xsl:template match="bibref">
<xsl:variable name="name" select="."/>
<xsl:for-each select="document('bib.xml')">
<xsl:apply-templates select="key('bib',$name)"/>
</xsl:for-each>
</xsl:template>
12.3 Форматирование чисел
Функция: строка format-number(число, строка, строка?)
Функция format-number преобразует свой первый аргумент в строку, используя строку шаблона форматирования, представленную во втором аргументе, и десятичный формат, поименованый в третьем аргументе, либо десятичный формат по умолчанию, если третий аргумент отсутствует. Строка с шаблоном форматирования имеет синтаксис, определенный в JDK 1.1 для класса DecimalFormat. Строка шаблона форматирования представлена в локализованной нотации: десятичный формат определяет, какие именно символы в шаблоне имеют специальное значение (за исключением символа кавычки, который не подлежит локализации). Шаблон формата не должен содержать символ денежной единицы (#x00A4), такая возможность была добавлена уже после первой реализации JDK 1.1. Названием десятичного формата должно быть QName, которое приводится к расширенному имени как описано в главе [2.4 Полные имена]. Если в стиле отсутствует декларация десятичного формата с заданным расширенным именем, фиксируется ошибка.
Замечание: Разработчики не обязаны использовать именно реализацию JDK 1.1, а сам анализатор не обязательно реализовывать на Java.
Замечание: Чтобы контролировать округление чисел, в стилях могут использоваться другие функции из XPath.
<!-- Category: top-level-element -->
<xsl:decimal-format
name = qname
decimal-separator = char
grouping-separator = char
infinity = string
minus-sign = char
NaN = string
percent = char
per-mille = char
zero-digit = char
digit = char
pattern-separator = char />
Элемент xsl:decimal-format
декларирует десятичный формат, который управляет интерпретацией шаблона формата, используемого в функции format-number. Если присутствует атрибут name
, данный элемент декларирует именованный десятичный формат. В остальных случаях декларируется десятичный формат по умолчанию. Значением атрибута name
является QName, которое приводится к расширенному имени как было описано в главе [2.4 Полные имена]. Если десятичный формат по умолчанию или десятичный формат с данным именем, декларируется несколько раз, фиксируется ошибка (даже при различном приоритете импорта). Это можно делать только если каждый раз для всех атрибутов декларированы одни и те же значения (принимая во внимание все значения по умолчанию).
Остальные атрибуты xsl:decimal-format
соответствуют методам класса DecimalFormatSymbols из JDK 1.1. Для каждой пары методов get
/set
в элементе xsl:decimal-format
определен соответствующий атрибут.
Следующие атрибуты задают интерпретацию символов в шаблоне формата, а также указывают символы, которые могут появиться в результате форматирования числа:
decimal-separator
задает символ, используемый как десятичная точка, по умолчанию используется символ точки (.
)
grouping-separator
задает символ, используемый как разделитель при группировке (например, тысяч), по умолчанию используется символ запятой (,
)
percent
задает символ, используемый как символ процента, по умолчанию используется символ процента (%
)
per-mille
задает символ, используемый как символ промилле, по умолчанию используется символ промилле из набора Unicode (#x2030)
zero-digit
задает символ, используемый как цифра нуль, по умолчанию используется цифра нуль (0
)
Следующие атрибуты задают интерпретацию символов в шаблоне формата:
digit
задает символ, используемый в шаблоне формата для обозначения цифр, по умолчанию таковым является символ решетки (#
)
pattern-separator
задает символ, используемый для разделения положительной и отрицательной частей в шаблоне, по умолчанию используется символ точки с запятой (;
)
Следующие атрибуты определяют символы или строки, которые могут появиться в результате форматирования числа:
infinity
задает строку, используемую для обозначения бесконечности, по умолчанию используется строка Infinity
NaN
задает строку, используемую для представления значения NaN, по умолчанию используется строка NaN
minus-sign
задает символ, используемый по умолчанию как знак "минус", по умолчанию используется символ тире-минус (-
, #x2D)
12.4 Различные дополнительные функции
Функция: набор-узлов current()
Функция current возвращает набор узлов, состоящий из единственного члена - текущего узла. Для внешнего выражения (выражения, которое не является частью другого выражения), текущий узел всегда тот же самый, что и узел контекста. Таким образом,
<xsl:value-of select="current()"/>
означает то же самое, что и
<xsl:value-of select="."/>
Однако внутри квадратных скобок текущий узел обычно отличается от узла контекста. Например,
<xsl:apply-templates select="//glossary/item[@name=current()/@ref]"/>
будет обрабатывать все элементы item
, которые имеют родителем элемент glossary
, а также имеют атрибут name
, значение которого равно значению атрибута ref
текущего узла. Этот вариант отличается от
<xsl:apply-templates select="//glossary/item[@name=./@ref]"/>
который означает то же самое, что
<xsl:apply-templates select="//glossary/item[@name=@ref]"/>
а потому будет обрабатывать все элементы item
, которые имеют родителем элемент glossary
, а также имеют атрибуты name
и ref
с одинаковыми значениями.
Если в шаблоне использовать функцию current, фиксируется ошибка.
Функция: строка unparsed-entity-uri(строка)
unparsed-entity-uri возвращает URI неразобранной сущности с заданным именем, находящейся в том же документе, что и узел контекста (см. [3.3 Неразобранные сущности]). Если такой сущности нет, функция возвращает пустую строку.
Функция: строка generate-id(список-узлов?)
Функция generate-id возвращает строку, уникальным образом идентифицирующую тот узел из набора узлов, представленного в аргументе, который первым встретится в документе. Уникальный идентификатор должен состоять из алфавитно-цифровых символов ASCII и должен начинаться с буквы. Таким образом, данная строка синтаксическим соответствует имени XML. Разработчик волен генерировать идентификатор любым удобным ему способом при условии, что для одного и того же узла всегда генерируется один и тот же идентификатор, а для разных узлов всегда генерируются разные идентификаторы. Процессор не обязан генерировать одни и те же идентификаторы при каждом преобразовании документа. Нет гарантий, что сгенерированный уникальный идентификатор не совпадет с каким-либо уникальным ID, указанным у исходном документе. Если в аргументе был дан пустой набор узлов, функция возвращает пустую строку. Если аргумент отсутствует, то по умолчанию используется узел контекста.
Функция: object system-property(строка)
Аргумент функции должен обрабатываться как строка QName. QName приводится к расширенному имени с помощью деклараций пространства имен в области видимости данного выражения. Функция system-property возвращает объект, представляющий значение системного параметра, идентифицируемого этим именем. Если такого системного свойства нет, должна возвращаться пустая строка.
Реализации процессора должны представлять следующие системные свойства, относящиеся к пространству имен XSLT:
xsl:version
, число, указывающее версию XSLT, реализуемую данным процессором. Для XSLT процессоров, реализующих версию XSLT, описываемую данным документом, таким числом является 1.0
xsl:vendor
, строка, идентифицирующая разработчика XSLT процессора
xsl:vendor-url
, строка, содержащая URL, идентифицирующий разработчика данного XSLT процессора. Как правило, это страница хоста (домашняя страница) Web-сайта разработчика.
Назад |
Содержание |
Вперед