Счетчики XQuery внутри для - PullRequest
       27

Счетчики XQuery внутри для

5 голосов
/ 13 апреля 2011

Допустим, у меня есть код 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

но, конечно, это тоже не сработало: (.

Любые предложения будут высоко оценены. Также, можете ли вы предложитьхорошая книга / учебник / сайт для таких вещей?

Ответы [ 4 ]

17 голосов
/ 13 апреля 2011

Вам это не нужно очень часто, но если вам действительно нужна переменная-счетчик внутри XQuery для выражения (аналогично position () в xsl: for-each), вы можете использовать переменную at в

for $x at $pos in //item return
  <item position="{$pos}" value="{string($x)}"/>
1 голос
/ 13 апреля 2011

Я не думаю, что вы поняли основы декларативной парадигмы.

Общее количество и сумма будет:

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))
0 голосов
/ 02 июля 2015

Вот еще одно решение, если вы не хотите рассчитывать или действовать на каждый элемент коллекции, но вы хотите рассчитывать / действовать только, если применяется определенное условие. В этом случае вы можете вспомнить парадигму функционального программирования 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 ...

0 голосов
/ 28 апреля 2014

Чтобы отобразить счетчик в цикле, лучший и более простой способ - добавить в $ pos в цикл for.$ pos будет работать как счетчик.

Фрагмент кода:

{for $artist **at $pos** in (/ns:Entertainment/ns:Artists/ns:Name)

  return
      <tr><td>{$pos}&nbsp;&nbsp;
    {$artist}</td></tr>

}

Вывод:

1   Artist

2   Artist 

3   Artist 

4   Artist

5   Artist

6   Artist
...