XQuery - неверные индексы в подстроке после использования функции обратной строки

Я пытаюсь реализовать base64-кодирование очень простым способом. В моем подходе (давайте на секунду уберем, уместно ли это или нет), мне нужно перевернуть строки и затем констатировать их. После этого эта объединенная строка используется в функции подстроки. Строки соединяются правильно, но при использовании подстроки basex, похоже, теряет ее.

Самое смешное, что подстрока работает хорошо для всех индексов, начиная с 8. Поэтому подстрока ($string, 1, 8) и выше дает правильный вывод. Но все, что ниже, запутано. Начиная с одного исчезнувшего числа: подстрока ($string, 1, 7 (и ниже)) приводит к длине строки 6. Причем подстрока может начинаться только с 1-го или 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 ответ

Решение

Хорошо, так что я понял это, я думаю.

Прежде всего в функции 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)  } ;

Я увидел, что мой ввод выглядел так:

Очевидно, он должен был зацикливаться где-то без цикла for clear, и, поскольку я новичок в Xquery, я, должно быть, пропустил это. И действительно. Я нашел это в функции проверки-восемь:

>  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, но по какой-то причине он работает не так, как я ожидал. Так что это может быть не для вас, если есть аналогичные проблемы.

В этот момент стало ясно, что let $fullBinary не может быть подана в выражении FLWR, по крайней мере, не может вызвать функцию concat-strings. Я изменил его, и теперь он производит только строку, и теперь я пытаюсь выяснить новую последовательность запуска всего модуля, но я думаю, что основная проблема здесь решена.

Другие вопросы по тегам