#xslt #xslt-2.0 #xpath-2.0
#xslt #xslt-2.0 #xpath-2.0
Вопрос:
Я пытаюсь понять, как XSL обрабатывает for-each . Изначально я написал рекурсивную функцию выбора значений (отфильтровывает все строки, которые не соответствуют шаблону регулярных выражений) следующим образом:
<!-- Ver.1 -->
<xsl:function name="choose-values">
<xsl:param name="values" />
<xsl:param name="pattern" as="xs:string" />
<xsl:choose>
<xsl:when test="count($values) = 0" >
<xsl:sequence select="()" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="tail"
select="choose-values(subsequence($values, 2), $pattern)" />
<xsl:variable name="value" select="$values[1]" />
<xsl:sequence select="if (matches($value, $pattern))
then ($value, $tail)
else $tail" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
Затем я наткнулся <xsl:for-each>
и переписал его следующим образом:
<!-- Ver.2 -->
<xsl:function name="choose-values">
<xsl:param name="values" />
<xsl:param name="pattern" as="xs:string" />
<xsl:for-each select="$values">
<xsl:if test="matches(., $pattern)">
<xsl:sequence select="." />
</xsl:if>
</xsl:for-each>
</xsl:function>
Являются ли эти две версии эквивалентными? (мои тесты показывают это). Я пропускаю некоторые крайние случаи в версии 2?
Просто чтобы прояснить ситуацию, это не вопрос домашнего задания. Я просто пытаюсь понять различия (если таковые имеются), используя простой пример.
Комментарии:
1. Я понимаю, что это не ответ на ваш вопрос, но мне интересно, почему вы просто не используете
$values[matches(., $pattern)]
. Конечно, нет необходимости писать функцию для фильтрации элементов в последовательности XSLT / XPath 2.0, язык XPath имеет предикаты для этой цели.2. Ну, это был просто надуманный пример, иллюстрирующий рекурсию и точку итерации. В моем реальном коде функция, применяемая к каждому элементу, сложнее, чем обычная matches() .
Ответ №1:
Да, два образца кажутся эквивалентными. Как правило, вам не нужна рекурсия в XSLT, если обработка одного элемента в последовательности каким-либо образом не зависит от обработки предыдущих элементов. Если каждый элемент обрабатывается независимо от других, вы можете использовать выражения фильтра или выражения сопоставления, одним из примеров которых является xsl:for-each . Преимущество выполнения этого способа (помимо удобочитаемости кода) заключается в том, что вы не навязываете порядок обработки, что дает оптимизатору больше свободы для работы с его магией.
Ответ №2:
Являются ли эти две версии эквивалентными? (мои тесты показывают это). Я пропускаю некоторые крайние случаи в версии 2?
Похоже, они дают одинаковые результаты — трудно сказать, потому что оба фрагмента кода излишне сложны.
Это можно сделать просто:
<xsl:sequence select="$values[matches(., $pattern)]"/>