Рекурсивный вызов XSL — xsl: функции против xsl: шаблон с шаблоном вызова

#xslt #xslt-2.0 #xslt-1.0

#xslt #xslt-2.0 #xslt-1.0

Вопрос:

У меня есть базовый запрос. Я использую xsl: template и использую call tempate для выполнения рекурсивных вызовов шаблона. Я вижу xsl: функцию, которая также может выполнять рекурсивные вызовы функций, подобные рекурсивным вызовам шаблонов, и достигать того же. Когда следует использовать xsl: функцию и когда следует использовать xsl: шаблон. Я не уверен, в чем разница между ними и когда их следует использовать. Каковы особенности каждого из них. Может кто-нибудь, пожалуйста, помочь мне лучше понять это.

Комментарии:

1. Хороший вопрос, 1. Смотрите мой ответ для объяснения, сравнения и рекомендации.

Ответ №1:

Вот как я ответил на аналогичный вопрос почти 3 года назад:

Преимущества использования <xsl:function/> :

  1. Возможность компоновки.

  2. Отлично смотрится в выражении, которое использует его как параметр, как возвращаемое значение или как частичное приложение.

  3. Удобочитаемость (компактность) и ремонтопригодность.

  4. Более слабая связь (не зависит от неявного узла контекста)

  5. Может ссылаться в выражении XPath

Недостатки:

  1. Параметры идентифицируются только по позиции (не по имени)

  2. Может быть нечистым (может иметь побочный эффект, такой как создание новых узлов), и просто взглянув на выражение, ссылающееся на эту функцию, люди могут не понять, что у него есть побочный эффект. Однако эту возможность путаницы можно устранить, если использовать правильное именование.

Я всегда склонен использовать <xsl:function/> . В случаях, когда функция создает новый узел (ы), я следую соглашению начинать его локальное имя со строки «make», как в makePerson() .

Я могу только добавить к этому:

Всегда, когда это возможно, используйте <xsl:function> .

В XPath 3.0 функции являются первоклассным типом данных языка (он же HOF — функции высшего порядка). Они могут быть переданы в качестве параметров или возвращены в качестве результата в / из других функций.

Это невероятно мощный шаг вперед по сравнению с использованием именованных шаблонов.

Ответ №2:

Концептуально xsl:apply-templates это отображение с полиморфной функцией, выраженной для всех объявленных вами правил. xsl:function объявляет «обычную» функцию, которую вы можете использовать в любой другой инструкции или объявлении, принимающем выражения XPath. xsl:call-template инструкция «вызывает» конкретный именованный шаблон (вы могли бы думать об этом как о функции в некотором роде).

Из-за этого существуют различия в том, как задействован контекст вычисления в каждом из них: xsl:apply-templates определяет новый контекстный список, из которого берется узел контекста, а также положение близости; xsl:function не имеет определенного узла контекста (полагаться на это ошибка); xsl:call-template не изменяет контекст вычисления.

Другим очевидным отличием является их взаимосвязь с выводом: как xsl:apply-templates , так и xsl:call-template инструкции as XSLT выводят свою сконструированную последовательность; xsl:function как часть выражения XPath этого не происходит.

Комментарии:

1. @Alejandro: Я нахожу в вашем ответе два утверждения, которые являются проблематичными (не совсем верными). 1) » xsl:function у него не определен контекстный узел (полагаться на него — ошибка) «; Точнее было бы сказать, что процессор XSLT должен выдавать ошибку, если в теле функции встречается относительное выражение XPath. 2) «xsl: функция как часть выражения XPath, это не так. (вывод построенной последовательности)». Это неправда. xsl:function Можно создавать узлы и возвращать их — я использую этот метод. Да, xsl:function может иметь побочные эффекты.

2.@Dimitre: От w3.org/TR/xslt20/#stylesheet-functions «В теле функции таблицы стилей фокус изначально не определен; это означает, что любая попытка сослаться на элемент контекста, положение контекста или размер контекста является невосстанавливаемой динамической ошибкой».О двух: в результирующее дерево выводится не функция, а инструкция XSLT. Что касается побочных эффектов, ну, это можно оспорить: даже функции, которые создают новые узлы в качестве результата, будут создавать тот же результат для того же аргумента, кроме того, что у него может быть другой идентификатор узла.

3. @Dimitre: По теме: похоже, что был крупный ретег, который изменил все xpathengines теги, чтобы xpath даже изменить атрибуцию для издания (если я пометил xpathengines теперь это говорит о том, что я пометил его xpath ). Следите за обсуждением на meta.stackexchange.com/questions/89005 /…

4. @alejandro: Когда функция возвращает generate-id() созданного узла, она возвращает различный результат для одного и того же аргумента — при каждом вызове.

5. @Dimitre: Это то, что я сказал: он возвращает одни и те же узлы (глубокие равенства), но они могут не иметь одинакового идентификатора (обратите внимание, что это не гарантируется ни в том, ни в другом случае. В некоторых спецификациях это утверждение является явным.) Это не оспаривает тот факт, что вы можете объявить нестабильную функцию и (как и в любом декларативном языке) вы можете безопасно моделировать это с помощью моноидов.

Ответ №3:

Я нашел ответ Димитра — http://www.stylusstudio.com/xsllist/200811/post00400.html — полезно.

Преимущества использования <xsl:function/> :

  1. Возможность компоновки.

  2. Отлично смотрится в выражении, которое использует его как параметр, как возвращаемое значение или как частичное приложение.

  3. Удобочитаемость (компактность) и ремонтопригодность.

  4. Более слабая связь (не зависит от неявного узла контекста)

  5. Может ссылаться в выражении XPath

Недостатки:

  1. Параметры идентифицируются только по позиции (не по имени)

  2. Может быть нечистым (может иметь побочный эффект, такой как создание новых узлов), и просто взглянув на выражение, ссылающееся на эту функцию, люди могут не понять, что у него есть побочный эффект. Однако эту возможность путаницы можно устранить, если использовать правильное именование.

Я всегда склонен использовать <xsl:function/> . В случаях, когда функция создает новый узел (ы), я следую соглашению начинать его локальное имя со строки «make», как в makePerson() .

Ответ №4:

 Templates are useful when you have the requirement to store the results of each recursion into a variable as a attribute ( at the end of each recursion before calling the next ).

**Example:**

    <xsl:variable name="test">
     <record>
        <xsl:call-template name="templateRecursion">
              <xsl:with-param name="xyz" select="xyz"/>   
        </xsl:call-template>
     <record>
    </xsl:variable>

**templateRecursion:**

    <xsl:template name="templateRecursion">

    <!-- Do processing -->
     <xsl:attribute name="" value=""

    </xsl:template>

So, the variable test will have 

    <record>
     <attribute_name="" value=""/>
      .
      .
    </record>