Reputation: 129
We have below Input
<root>
<Input>1010</Input>
<ReadInput>a123c123</ReadInput>
</root>
Input tag indicates there must be two elements in output (AAAA and CCCC) which is indicated by 1 and each has 4 characters.
1 - AAAA is ON
0 - BBBB is OFF
1 - CCCC is ON
0 - DDDD is OFF
Hence the below Ouput:
Output
<Result>
<AAAA>a123</AAAA>
<CCCC>b123</CCCC>
</Result>
Now the problem is I have all 26 elements upto Z. So when creating Z element we need to check for availability of all the elements before it with '1' as their index in tag. Can this be achieved in xquery. Further, we are looking for a way to set global variable inside a function to achieve this and looks lilke its not possible in xquery.
Upvotes: 0
Views: 1064
Reputation: 163458
I think this is best tackled with a recursive function
declare function local:f($root as element(root), $i as xs:integer, $j as xs:integer) {
if (string-length($root/Input) le $i)
then if ((substring($root/Input, $i, 1) eq '1')
then (element { local:tag($i) }
{ substring($root/ReadInput, $j, 4 },
local:f($root, $i+1, $j+4))
else local:f($root, $i+1, $j)
else ()
};
declare function local:tag($i as xs:integer) {
let $n := format-integer($i, 'A')
return $n||$n||$n||$n
};
local:f(root, 1, 1)
Upvotes: 1
Reputation: 167706
With XQuery 3 and the analyze-string
function you could break up the data into sequences and use
<Result>
{
let
$bits as xs:integer* := analyze-string(root/Input, '[01]')//*:match!xs:integer(.),
$values as xs:string* := analyze-string(root/ReadInput, '.{4}')//*:match!string(),
$element-names as xs:string* := (string-to-codepoints('A') to string-to-codepoints('Z'))!codepoints-to-string(.)!(. || . || . || .),
$positions := $bits[. = 1]!index-of($bits, .),
$output-elements as xs:string* := $element-names[position() = $positions]
return
for $n at $pos in $output-elements
return element {$n} { $values[$pos] }
}
</Result>
http://xqueryfiddle.liberty-development.net/eiQZDba
As an alternative you could use substring
:
<Result>
{
let
$bitString as xs:string := root/Input/string(),
$bits as xs:integer* := for $p in 1 to string-length($bitString) return xs:integer(substring($bitString, $p, 1)),
$valueString as xs:string := root/ReadInput/string(),
$values as xs:string* := for $p in 0 to count($bits[. = 1]) - 1 return substring($valueString, 1 + $p * 4, 4),
$element-names as xs:string* := (string-to-codepoints('A') to string-to-codepoints('Z'))!codepoints-to-string(.)!concat(., ., ., .),
$positions := $bits[. = 1]!index-of($bits, .),
$output-elements as xs:string* := $element-names[position() = $positions]
return
for $n at $pos in $output-elements
return element {$n} { $values[$pos] }
}
</Result>
http://xqueryfiddle.liberty-development.net/eiQZDba/1
Upvotes: 1