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函数。我更改了它,现在它只生成字符串,现在我试图找出 运行 整个模块的新序列,但我认为这里的主要问题已经解决。