XSLT xsl: последовательность. Для чего это..?
Я знаю, что следующий вопрос - это немного новичков, но мне нужна ваша помощь, чтобы понять базовую концепцию.
Я хотел бы сначала сказать, что я программист XSLT в течение 3 лет, и все же есть некоторые новые и довольно базовые вещи, которые я изучал здесь, я никогда не знал (на моей работе кто-то учится программировать один, там не входит в курс).
Мой вопрос:
Каково использование xsl:sequence
?
Я использовал xsl:copy-of
, чтобы скопировать node как есть, xsl:apply-templates
для модификации выбранных узлов и value-of
для простого текста.
У меня никогда не было необходимости использовать xsl:sequence
. Я был бы признателен, если бы кто-нибудь мог показать мне пример использования xsl:sequence
, который является предпочтительным или не может быть достигнут без тех, которые я отметил выше.
Еще одна вещь, которую я читал о определении xsl:sequence
, конечно, но я не мог понять, как это полезно.
Ответы
Ответ 1
<xsl:sequence>
по атомному значению (или порядку атомных значений) совпадает с <xsl:copy-of>
, как только возвращают копию их ввода. Разница возникает, когда вы рассматриваете узлы.
Если $n - это один элемент node, например, определенный как-то вроде
<xsl:variable name="n" select="/html"/>
Тогда
<xsl:copy-of select="$n"/>
Возвращает копию node, имеет одно и то же имя и дочернюю структуру, но это новый node с новым идентификатором (и без родителя).
<xsl:sequence select="$n"/>
Возвращает node $n, возвращенный node имеет тот же родитель, что и $n, и равен ему оператором is
Xpath.
Разница почти полностью маскируется в традиционном использовании шаблона (стиль XSLT 1), так как вы никогда не получаете доступ к результату любой операции, результат конструктора неявно копируется в выходное дерево, так что тот факт, что xsl:sequence
doesn ' t сделать копию замаскирована.
<xsl:template match="a">
<x>
<xsl:sequence select="$n"/>
</x>
</xsl:template>
совпадает с
<xsl:template match="a">
<x>
<xsl:copy-of select="$n"/>
</x>
</xsl:template>
Оба создают новый элемент node и копируют результат содержимого в виде дочерних элементов нового node x
.
Однако различие быстро видно, если вы используете функции.
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="data:,f">
<xsl:variable name="s">
<x>hello</x>
</xsl:variable>
<xsl:template name="main">
::
:: <xsl:value-of select="$s/x is f:s($s/x)"/>
:: <xsl:value-of select="$s/x is f:c($s/x)"/>
::
:: <xsl:value-of select="count(f:s($s/x)/..)"/>
:: <xsl:value-of select="count(f:c($s/x)/..)"/>
::
</xsl:template>
<xsl:function name="f:s">
<xsl:param name="x"/>
<xsl:sequence select="$x"/>
</xsl:function>
<xsl:function name="f:c">
<xsl:param name="x"/>
<xsl:copy-of select="$x"/>
</xsl:function>
</xsl:stylesheet>
Выдает
$ saxon9 -it main seq.xsl
<?xml version="1.0" encoding="UTF-8"?>
::
:: true
:: false
::
:: 1
:: 0
::
Здесь результаты xsl:sequence
и xsl:copy-of
радикально различны.
Ответ 2
Наиболее распространенным вариантом использования для xsl: sequence является возврат результата из функции xsl:.
<xsl:function name="f:get-customers">
<xsl:sequence select="$input-doc//customer"/>
</xsl:function>
Но он также может быть полезен в других контекстах, например
<xsl:variable name="x" as="element()*">
<xsl:choose>
<xsl:when test="$something">
<xsl:sequence select="//customer"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="//supplier"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Главное, что он возвращает ссылки на исходные узлы, он не создает новые копии.
Ответ 3
Чтобы вернуть значение определенного типа, вы используете xsl:sequence
как xsl:value-of
, несмотря на то, что его имя всегда создает текст node (с XSLT 1.0).
Итак, в теле функции вы используете
<xsl:sequence select="42"/>
чтобы вернуть значение xs:integer
, вы должны использовать
<xsl:sequence select="'foo'"/>
чтобы вернуть значение xs:string
и
<xsl:sequence select="xs:date('2013-01-16')"/>
чтобы вернуть значение xs:date
и т.д. Конечно, вы также можете возвращать последовательности, например. <xsl:sequence select="1, 2, 3"/>
.
Вы не хотели бы создавать текст node или даже элемент node в этих случаях на мой взгляд, поскольку он неэффективен.
Итак, это мой подход, с новой системой типа XSLT и XPath 2.0, основанной на схеме, необходим способ вернуть или передать значения этих типов и создать новую конструкцию.
Майкл Кей говорит в своей "XSLT 2.0 и XPath 2.0 программист" около xsl:sequence
: "Эта невинно выглядящая инструкция, представленная в XSLT 2.0, имеет далеко идущие последствия для возможностей языка XSLT, потому что это означает, что Инструкции XSLT и конструкторы последовательностей (и, следовательно, функции и шаблоны) становятся способными возвращать любое значение, разрешенное моделью данных XPath. Без этого инструкции XSLT могут использоваться только для создания новых узлов в дереве результатов, но вместе с ним они также могут вернуть атомные значения и ссылки на существующие узлы.".
Ответ 4
Другое использование - создать тег, только если у него есть дочерний элемент. Требуется пример:
<a>
<b>node b</b>
<c>node c</c>
</a>
Где-то в вашем XSLT:
<xsl:variable name="foo">
<xsl:if select="b"><d>Got a "b" node</d></xsl:if>
<xsl:if select="c"><d>Got a "c" node</d></xsl:if>
</xsl:variable>
<xsl:if test="$foo/node()">
<wrapper><xsl:sequence select="$foo"/></wrapper>
</xsl:if>
Здесь вы можете увидеть демо: http://xsltransform.net/eiZQaFz
Это лучше, чем тестирование каждого тега следующим образом:
<xsl:if test="a|b">...</xsl:if>
Потому что вы в конечном итоге отредактируете его в двух местах. Также скорость обработки будет зависеть от того, какие теги находятся в вашем вменении. Если это последний из вашего теста, двигатель проверяет присутствие всех раньше. Поскольку $foo/ node() - это идиомы для "есть ли дочерний элемент?", Движок может его оптимизировать. Делая это, вы облегчаете жизнь всем.