我们有以下输入
<root>
<Input>1010</Input>
<ReadInput>a123c123</ReadInput>
</root>
输入标签表示输出中必须有两个元素(AAAA和CCCC),由1表示,每个元素有4个字符。
1 - AAAA is ON
0 - BBBB is OFF
1 - CCCC is ON
0 - DDDD is OFF
因此下面的输出:
输出
<Result>
<AAAA>a123</AAAA>
<CCCC>b123</CCCC>
</Result>
现在的问题是我将所有26个元素都放到Z.所以在创建Z元素时,我们需要检查所有元素的可用性,并以'1'作为标记中的索引。 这可以在xquery中实现。此外,我们正在寻找一种方法来在函数内部设置全局变量来实现这一点,并且看起来在xquery中不可能。
答案 0 :(得分:1)
使用XQuery 3和analyze-string
功能,您可以将数据分解为序列并使用
<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
作为替代方案,您可以使用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>
答案 1 :(得分:1)
我认为最好使用递归函数来解决这个问题
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)