#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/>
:
Возможность компоновки.
Отлично смотрится в выражении, которое использует его как параметр, как возвращаемое значение или как частичное приложение.
Удобочитаемость (компактность) и ремонтопригодность.
Более слабая связь (не зависит от неявного узла контекста)
Может ссылаться в выражении XPath
Недостатки:
Параметры идентифицируются только по позиции (не по имени)
Может быть нечистым (может иметь побочный эффект, такой как создание новых узлов), и просто взглянув на выражение, ссылающееся на эту функцию, люди могут не понять, что у него есть побочный эффект. Однако эту возможность путаницы можно устранить, если использовать правильное именование.
Я всегда склонен использовать
<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/>
:
Возможность компоновки.
Отлично смотрится в выражении, которое использует его как параметр, как возвращаемое значение или как частичное приложение.
Удобочитаемость (компактность) и ремонтопригодность.
Более слабая связь (не зависит от неявного узла контекста)
Может ссылаться в выражении XPath
Недостатки:
Параметры идентифицируются только по позиции (не по имени)
Может быть нечистым (может иметь побочный эффект, такой как создание новых узлов), и просто взглянув на выражение, ссылающееся на эту функцию, люди могут не понять, что у него есть побочный эффект. Однако эту возможность путаницы можно устранить, если использовать правильное именование.
Я всегда склонен использовать
<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>