Подтвердить что ты не робот

XSLT xsl: последовательность. Для чего это..?

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

Я хотел бы сначала сказать, что я программист XSLT в течение 3 лет, и все же есть некоторые новые и довольно базовые вещи, которые я изучал здесь, я никогда не знал (на моей работе кто-то учится программировать один, там не входит в курс).

Мой вопрос: Каково использование xsl:sequence?

Я использовал xsl:copy-of, чтобы скопировать node как есть, xsl:apply-templates для модификации выбранных узлов и value-of для простого текста.

У меня никогда не было необходимости использовать xsl:sequence. Я был бы признателен, если бы кто-нибудь мог показать мне пример использования xsl:sequence, который является предпочтительным или не может быть достигнут без тех, которые я отметил выше.

Еще одна вещь, которую я читал о определении xsl:sequence, конечно, но я не мог понять, как это полезно.

4b9b3361

Ответ 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() - это идиомы для "есть ли дочерний элемент?", Движок может его оптимизировать. Делая это, вы облегчаете жизнь всем.