Мне нужно вести подсчет предметов, которые
соответствовать условию во время цикла
через список узлов, используя for-each.
Я использовал position (), но это
неправильно, так как мне нужно продолжать работать
общий.
Любая помощь будет очень признательна.
В XSLT это обычно можно сделать с помощью рекурсии.
FXSL предлагает простой способ создания снимка шагов вычисления.
Используйте scanl
или scanl1
шаблон / функцию FXSL
В XSLT 1.0 это преобразование:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:myAdd="f:myAdd"
xmlns:myParam="f:myParam"
>
<xsl:import href="scanl.xsl"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<!-- To be applied on: numList.xml -->
<myAdd:myAdd/>
<myParam:myParam>0</myParam:myParam>
<xsl:template match="/">
<xsl:variable name="vFun" select="document('')/*/myAdd:*[1]"/>
<xsl:variable name="vZero" select="document('')/*/myParam:*[1]"/>
<xsl:call-template name="scanl">
<xsl:with-param name="pFun" select="$vFun"/>
<xsl:with-param name="pQ0" select="$vZero" />
<xsl:with-param name="pList" select="/*/num"/>
</xsl:call-template>
- - - - - - - - - - -
<xsl:call-template name="scanl1">
<xsl:with-param name="pFun" select="$vFun"/>
<xsl:with-param name="pList" select="/*/num"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="myAdd:*" mode="f:FXSL">
<xsl:param name="pArg1" select="0"/>
<xsl:param name="pArg2" select="0"/>
<xsl:value-of select="$pArg1 + $pArg2"/>
</xsl:template>
</xsl:stylesheet>
при применении к этому документу XML :
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
производит промежуточные суммы (промежуточные результаты вычисления sum()
):
<el>0</el>
<el>1</el>
<el>3</el>
<el>6</el>
<el>10</el>
<el>15</el>
<el>21</el>
<el>28</el>
<el>36</el>
<el>45</el>
<el>55</el>
- - - - - - - - - - -
<el>01</el>
<el>3</el>
<el>6</el>
<el>10</el>
<el>15</el>
<el>21</el>
<el>28</el>
<el>36</el>
<el>45</el>
<el>55</el>
Соответствующее преобразование XSLT 2.0, дающее тот же результат, это :
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
exclude-result-prefixes="f">
<xsl:import href="../f/func-scanl.xsl"/>
<xsl:import href="../f/func-Operators.xsl"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:value-of separator=", " select="f:scanl(f:add(), 0, /*/*)"/>
<xsl:text>
- - - - - - - - - - -
</xsl:text>
<xsl:value-of separator=", " select="f:scanl1(f:add(), /*/*)"/>
</xsl:template>
</xsl:stylesheet>
Вы можете передать в качестве параметра f:scanl()
любую функцию с двумя аргументами, первый из которых является текущим накопленным результатом, а второй - текущим элементом последовательности, переданным в f:scanl()
в качестве последнего аргумента. Второй аргумент f:scanl()
является начальным значением аккумулятора. Как правило, это будет 0
для суммирования и 1
для вычисления продукта.
f:scanl1()
почти совпадает с f:scan()
, но требует, чтобы аргумент последовательности был не пустым, и использует свой первый элемент в качестве начального значения аккумулятора.