#xml #xquery #counter
#xml #xquery #счетчик
Вопрос:
Допустим, у меня есть приведенный ниже код XQuery:
for $y in doc("file.xml")/A/B
for $x in $y/C where $x/constraint1 != "-" and $x/constraint2 > 2.00
do stuff
Могу ли я использовать счетчик, чтобы подсчитать, сколько мой код введет во второй цикл for?
Я попробовал это:
for $y in doc("file.xml")/A/B
let $i := 0
for $x in $y/C where $x/constraint1 != "-" and $x/constraint2 > 2.00
$i := $i 1
но я получил ошибки компиляции. Мне также нужно суммировать некоторые ограничения, подобные этому:
for $y in doc("file.xml")/A/B
let $i := 0
let $sum := 0
for $x in $y/C where $x/constraint1 != "-" and $x/constraint2 > 2.13
$i := $i 1
$sum := $sum $x/constraint2
но, конечно, это тоже не сработало :(.
Любые предложения будут высоко оценены. Кроме того, можете ли вы предложить хорошую книгу / учебник / сайт для выполнения подобных действий?
Ответ №1:
Вам это не нужно очень часто, но если вам действительно нужна переменная counter внутри for
выражения XQuery position()
(аналогично xsl:for-each
в at
), вы можете использовать в — переменную
for $x at $pos in //item return
<item position="{$pos}" value="{string($x)}"/>
Ответ №2:
Я не думаю, что вы поняли основы декларативной парадигмы.
Общее количество и сумма будут:
let $items := doc('file.xml')/A/B/C[constraint1 != '-' and constraint2 > 2.13]
return ('Count:', count($items), 'Sum:', sum($items/constraint2))
Частичное количество и сумма будут:
let $items := doc('file.xml')/A/B/C[constraint1 != '-' and constraint2 > 2.13]
for $pos in (1 to count($items))
return ('Count:', $pos, 'Sum:', sum($items[position() le $pos]/constraint2))
Ответ №3:
Для отображения счетчика в цикле лучшим и более простым способом является добавление в $pos в вашем цикле for. $pos будет работать как счетчик.
Фрагмент кода :
{for $artist **at $pos** in (/ns:Entertainment/ns:Artists/ns:Name)
return
<tr><td>{$pos}amp;nbsp;amp;nbsp;
{$artist}</td></tr>
}
Вывод:
1 Artist
2 Artist
3 Artist
4 Artist
5 Artist
6 Artist
Ответ №4:
Вот другое решение, если вы не хотите подсчитывать или действовать с каждым элементом коллекции, но вы хотите подсчитывать / действовать только в том случае, если применяется определенное условие. В этом случае вы могли бы вспомнить парадигму функционального программирования XQuery и реализовать этот подсчет / действие с помощью рекурсивных вызовов функций:
declare function ActIf($collection as element(*)*, $index as xs:integer, $indexMax as xs:integer, $condition as xs:string, $count as xs:integer) as xs:integer
{
if($index <= $indexMax) then
let $element := $collection[$index]
if($element/xyz/text() eq $condition) then
(: here you can call a user-defined function before continuing to the next element :)
ActIf($collection, $index 1, $indexMax, $condition, $count 1)
else
ActIf($collection, $index 1, $indexMax, $condition, $count)
else (: no more items left:)
$count
};
Более простым способом было бы использование соответствующего выражения XPath:
for $element at $count in $collection[xyz = $condition]
return
(: call your user-defined function :)
или даже
myFunction($collection[xyz = $condition])
Рекурсивное решение может оказаться весьма полезным, если вы хотите реализовать что-то более сложное с помощью XQuery…