XQuery - 使用反向字符串函数后子字符串中的错误索引
XQuery - wrong indexes in substring after reverse-string function use
我正在尝试以一种非常简单的方式实现 base64 编码。在我的方法中(暂且不管它是否合适)我需要反转字符串然后连接它们。之后,此连接字符串用于子字符串函数。字符串连接正确,但当我使用子字符串时,basex 似乎丢失了它。
有趣的是 substring 适用于从 8 开始的所有索引。因此 substring($string, 1, 8) 和更高的值给出正确的输出。但是下面的一切都搞砸了。从一个消失的数字开始: substring($string, 1, 7 (and below) ) 导致 6 长度的字符串。
此外,子字符串只能从第 1 个或 0 个索引开始。任何更大的结果都是空的 return.
declare variable $array := [];
declare function bs:encode
( $input as xs:string ) {
bs:integer-to-binary(string-to-codepoints($input), "", $array)
} ;
declare function bs:integer-to-binary
( $input as xs:integer*, $string as xs:string, $array as array(xs:string) ) {
let $strings :=
for $i in $input
return
if ($i != 0)
then if ($i mod 2 = 0)
then bs:integer-to-binary(xs:integer($i div 2), concat($string, 0), $array)
else bs:integer-to-binary(xs:integer($i div 2), concat($string, 1), $array)
else if ($i <= 0)
then array:append($array, $string)
return bs:check-if-eight($strings)
} ;
declare function bs:check-if-eight
( $strings as item()+ ) {
let $fullBinary :=
for $string in $strings
return if (string-length($string) < 8)
then bs:check-if-eight(concat($string, 0))
else $string (: add as private below :)
return bs:concat-strings($fullBinary)
} ;
declare function bs:concat-strings
( $strings as item()+ ) {
let $firstStringToConcat := functx:reverse-string($strings[position() = 1])
let $secondStringToConcat := functx:reverse-string($strings[position() = 2])
let $thirdStringToConcat := functx:reverse-string($strings[position() = 3])
let $concat :=
concat
($firstStringToConcat,
$secondStringToConcat,
$thirdStringToConcat)
(: this returns correct string of binary value for Cat word :)
return bs:divide-into-six($concat)
} ;
declare function bs:divide-into-six
( $binaryString as xs:string) {
let $sixBitString := substring($binaryString, 1, 6)
(: this should return 010000 instead i get 000100 which is not even in $binaryString at all :)
return $sixBitString
} ;
bs:encode("Cat")
我希望字符串 (010000) 的前六个字母相反,我猜得到一些随机序列 (00100)。整个模块旨在将字符串编码为 base64 格式,但现在(我上传的部分)应该只为 'C'
抛出前六位
好吧,我想我明白了。
首先在函数 concat-strings 中,我将 concat 更改为 fn:string-join。它允许我作为分隔连接字符串的参数符号传递。
declare function bs:concat-strings ( $strings as item()+ ) {
let $firstStringToConcat := xs:string(functx:reverse-string($strings[position() = 1]))
let $secondStringToConcat := xs:string(functx:reverse-string($strings[position() = 2]))
let $thirdStringToConcat := xs:string(functx:reverse-string($strings[position() = 3]))
let $concat :=
****fn:string-join(****
($firstStringToConcat,
$secondStringToConcat,
$thirdStringToConcat),****'X'****)
return bs:divide-into-six($concat) } ;
我看到我的输入是这样的:
XXXXXXXX01000011XXXXXXXXXXXXXXXXX01100001XXXXXXXXXXXXXXXXX01110100XXXXXXXX
显然,它必须在没有明确 for 循环的情况下循环到某个地方,作为 Xquery 的新手,我一定错过了这一点。确实如此。我在 check-if-eight 函数中找到它:
> declare function bs:check-if-eight ( $strings as item()+ ) {
> **let $fullBinary :=**
> for $string in $strings
> return if (string-length($string) < 8)
> then bs:check-if-eight(concat($string, 0))
> else $string (: add as private below :)
> **return bs:concat-strings($fullBinary)** } ;
尽管在 FOR 关键字之上,$fullBinary 变量处于循环中并产生空格(?),当我使用 X 作为分隔符时,它清楚地显示出来。
免责声明:我之前考虑过这个问题并使用了 functx:trim 但由于某种原因它没有像我预期的那样工作。所以如果你有类似的问题,它可能也不适合你。
至此就清楚了,FLWR语句中let $fullBinary不能bid至少不能触发concat-strings函数。我更改了它,现在它只生成字符串,现在我试图找出 运行 整个模块的新序列,但我认为这里的主要问题已经解决。
我正在尝试以一种非常简单的方式实现 base64 编码。在我的方法中(暂且不管它是否合适)我需要反转字符串然后连接它们。之后,此连接字符串用于子字符串函数。字符串连接正确,但当我使用子字符串时,basex 似乎丢失了它。
有趣的是 substring 适用于从 8 开始的所有索引。因此 substring($string, 1, 8) 和更高的值给出正确的输出。但是下面的一切都搞砸了。从一个消失的数字开始: substring($string, 1, 7 (and below) ) 导致 6 长度的字符串。 此外,子字符串只能从第 1 个或 0 个索引开始。任何更大的结果都是空的 return.
declare variable $array := []; declare function bs:encode ( $input as xs:string ) { bs:integer-to-binary(string-to-codepoints($input), "", $array) } ; declare function bs:integer-to-binary ( $input as xs:integer*, $string as xs:string, $array as array(xs:string) ) { let $strings := for $i in $input return if ($i != 0) then if ($i mod 2 = 0) then bs:integer-to-binary(xs:integer($i div 2), concat($string, 0), $array) else bs:integer-to-binary(xs:integer($i div 2), concat($string, 1), $array) else if ($i <= 0) then array:append($array, $string) return bs:check-if-eight($strings) } ; declare function bs:check-if-eight ( $strings as item()+ ) { let $fullBinary := for $string in $strings return if (string-length($string) < 8) then bs:check-if-eight(concat($string, 0)) else $string (: add as private below :) return bs:concat-strings($fullBinary) } ; declare function bs:concat-strings ( $strings as item()+ ) { let $firstStringToConcat := functx:reverse-string($strings[position() = 1]) let $secondStringToConcat := functx:reverse-string($strings[position() = 2]) let $thirdStringToConcat := functx:reverse-string($strings[position() = 3]) let $concat := concat ($firstStringToConcat, $secondStringToConcat, $thirdStringToConcat) (: this returns correct string of binary value for Cat word :) return bs:divide-into-six($concat) } ; declare function bs:divide-into-six ( $binaryString as xs:string) { let $sixBitString := substring($binaryString, 1, 6) (: this should return 010000 instead i get 000100 which is not even in $binaryString at all :) return $sixBitString } ; bs:encode("Cat")
我希望字符串 (010000) 的前六个字母相反,我猜得到一些随机序列 (00100)。整个模块旨在将字符串编码为 base64 格式,但现在(我上传的部分)应该只为 'C'
抛出前六位好吧,我想我明白了。
首先在函数 concat-strings 中,我将 concat 更改为 fn:string-join。它允许我作为分隔连接字符串的参数符号传递。
declare function bs:concat-strings ( $strings as item()+ ) { let $firstStringToConcat := xs:string(functx:reverse-string($strings[position() = 1])) let $secondStringToConcat := xs:string(functx:reverse-string($strings[position() = 2])) let $thirdStringToConcat := xs:string(functx:reverse-string($strings[position() = 3])) let $concat := ****fn:string-join(**** ($firstStringToConcat, $secondStringToConcat, $thirdStringToConcat),****'X'****) return bs:divide-into-six($concat) } ;
我看到我的输入是这样的: XXXXXXXX01000011XXXXXXXXXXXXXXXXX01100001XXXXXXXXXXXXXXXXX01110100XXXXXXXX
显然,它必须在没有明确 for 循环的情况下循环到某个地方,作为 Xquery 的新手,我一定错过了这一点。确实如此。我在 check-if-eight 函数中找到它:
> declare function bs:check-if-eight ( $strings as item()+ ) { > **let $fullBinary :=** > for $string in $strings > return if (string-length($string) < 8) > then bs:check-if-eight(concat($string, 0)) > else $string (: add as private below :) > **return bs:concat-strings($fullBinary)** } ;
尽管在 FOR 关键字之上,$fullBinary 变量处于循环中并产生空格(?),当我使用 X 作为分隔符时,它清楚地显示出来。 免责声明:我之前考虑过这个问题并使用了 functx:trim 但由于某种原因它没有像我预期的那样工作。所以如果你有类似的问题,它可能也不适合你。
至此就清楚了,FLWR语句中let $fullBinary不能bid至少不能触发concat-strings函数。我更改了它,现在它只生成字符串,现在我试图找出 运行 整个模块的新序列,但我认为这里的主要问题已经解决。