XQuery-使用反向字符串函数后,子字符串中的索引错误

时间:2019-05-17 09:10:01

标签: xquery basex functx

我正在尝试以一种非常简单的方式实现base64编码。在我的方法中(不管是否合适,请先搁置一秒钟),我需要反转字符串,然后将它们连接起来。之后,此缩略的字符串用于子字符串功能。字符串已正确连接,但是当我使用substring时,basex似乎会丢失它。

有趣的是子串对于从8开始的所有索引都适用。因此,子串($ string,1,8)和更高的子串给出正确的输出。但是下面的所有东西都弄糟了。以一个消失的数字开头:substring($ string,1,7(及以下))产生6个长度的字符串。 此外,子字符串只能以1st或0索引开头。任何更大的结果都会带来空回报。

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'的前六位抛出

1 个答案:

答案 0 :(得分:0)

好的,所以我猜出来了。

首先在函数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语句中让$ fullBinary投标,至少不能触发concat-strings函数。我更改了它,现在它仅生成字符串,现在我试图找出运行整个模块的新顺序,但我认为这里的主要问题已解决。