XQuery - неверные индексы в подстроке после использования функции обратной строки - PullRequest
1 голос
/ 17 мая 2019

Я пытаюсь реализовать 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 Ответ

0 голосов
/ 17 мая 2019

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

Прежде всего в функции 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, я, должно быть, пропустил это. И действительно. Я нашел это в функции проверки, если-восемь:

>  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. Я изменил его, и теперь он производит только строку, и теперь я пытаюсь выяснить новую последовательность запуска всего модуля, но я думаю, что основная проблема здесь решена.

...