Im trying to count occurrences of a string during a for loop in a dictionary (baseX map). It seems that the contents of the dictionary are cleared after each iteration. Is there a way to keep the info throughout the loop?
declare variable $dict as map(*) := map:merge(());
for $x at $cnt in //a order by -$cnt
let $l := (if (map:contains($dict, $x/@line)) then (fn:number(map:get($dict, $x/@line))) else (0))
let $dict := map:put($dict, $x/@line, 1 + $l)
return (
$dict,
if ($x[@speaker="player.computer" or @speaker = "event.object"])
then ( <add sel="(//{fn:name($x)}[@line='{$x/@line}'])[{fn:string(map:get($dict, $x/@line))}]" type="@hidechoices">false</add> )
else ( <remove sel="(//{fn:name($x)}[@line='{$x/@line}'])[1]" />)
)
so for this xml:
<a line="x" />
<a line="y" />
<a line="y" />
<a line="z" />
i should get something like this for the first:
{
"x": 1
}
and this for the last iteration:
{
"x": 1,
"y": 2,
"z": 1
}
I have to construct some text out of this in the end, thats the last part of the output.
Right now i only get the current key/value pairs at each iteration, so $dict has only one entry throughout the whole execution, and $l is always 0.
Thankfully this worked:
for $x at $cnt in //a
let $dict := map:merge((
for $y at $pos in //a
let $line := $y/@line
where $pos <= $cnt
group by $line
return map:entry($line, count($y))
))
return (
$dict,
if ($x[@speaker="player.computer" or @speaker = "event.object"])
then ( <add sel="(//{fn:name($x)}[@line='{$x/@line}'])[{fn:string(map:get($dict, $x/@line))}]" type="@hidechoices">false</add> )
else ( <remove sel="(//{fn:name($x)}[@line='{$x/@line}'])[1]" />)
)
For some reason could not use position() to limit the inner for, it returned all nodes right at first iteration. Thanks a lot for your help!