Xquery在if条件中设置全局变量

时间:2018-01-08 09:28:01

标签: xquery osb

我们有以下输入

<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中不可能。

2 个答案:

答案 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>

http://xqueryfiddle.liberty-development.net/eiQZDba/1

答案 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)