我们有以下输入
<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中是不可能的。
发布于 2018-01-08 22:18:12
使用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>http://xqueryfiddle.liberty-development.net/eiQZDba/1
发布于 2018-01-09 18:06:26
我认为最好用递归函数来解决这个问题。
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) https://stackoverflow.com/questions/48147399
复制相似问题