"˙˙˙ sɐɯʇsᴉɹɥƆ ʎɹɹǝW" -- the JSONiq way

94 views
Skip to first unread message

her...@stamm-wilbrandt.de

unread,
Dec 19, 2013, 5:36:37 PM12/19/13
to jso...@googlegroups.com
Just did a short blog posting on this topic here.

In order to make that JSONiq script work on try.json.io the input needed to be incorporated into the script.
This works on Xidel processor as well.
JSON input cannot be processed directly, and I was not able to get the "let $m := pxp:json($raw);" trick work.

Next I wanted to "Share" on try.zorba.io, and to "permalink" on Xidel.
Unfortunately "Share" goes into an endless loop without providing a link.
And the Unicode characters in mapping string break "permalink" feature of Xidel.

Anyway, just copying as slightly modified DataPower JSONiq into both just works!
This is the diff:
$ diff upside-down-ascii.xq upside-down-ascii-inp.xq
3c3
< declare option jsoniq-version "0.4.42";
---
> (: declare option jsoniq-version "0.4.42"; :)
6c6
< declare variable $inp := .;
---
> declare variable $inp := [ "Merry Christmas,", "and a happy new year!", "(2014)" ];
$


Next I did try to get the "!" map feature working.
It is mentioned in the free JSONiq - The SQL of NoSQL in "III. 10. FLWOR Expressions, Map Operator".

(1 to 10) ! ($$ * 2)  in XQ--  or
(1 to 10) ! (. * 2)   in XQ++

is equivalent to
for $i in 1 to 10 return $i * 2

resulting in
2 4 6 8 10 12 14 16 18 20

I tried to make use of that in try.zorba.io
This diff produces "interesting" output:
$ diff upside-down-ascii-inp.xq a.xq
12c12
<   for $i in (1 to 31) return $i,  fn:string-to-codepoints($m)
---
>   for $i in (1 to 31) return 0,  fn:string-to-codepoints($m)
20,22c20
<           for $c in fn:string-to-codepoints($s)
<             return
<               fn:codepoints-to-string( $M[$c] )
---
>           fn:string-to-codepoints($s) ! fn:codepoints-to-string( $M[.] )
$

It seems that  $M[.]  is the problem, because this modified script does what it should:
$ diff a.xq b.xq
20c20
<           fn:string-to-codepoints($s) ! fn:codepoints-to-string( $M[.] )
---
>           fn:string-to-codepoints($s) ! fn:codepoints-to-string( . )
$


Outputs:
[ ")4102(", "!raey wen yppah a dna", ",samtsirhC yrreM" ]


Can somebody make "Share" work again on try.zorbo.io?
What is the problem with Xidel's "permalink"?
Is the  $M[.]  for map operator a bug in zorba engine?
Where can I find the map operation in JSONiq 1.0 spec?
(only found it in the JSONiq book)


Hermann.

Ghislain Fourny

unread,
Dec 20, 2013, 8:14:01 AM12/20/13
to jso...@googlegroups.com
Hi Hermann,

Nice :-) Here are some comments and answers to your questions.

> This diff produces "interesting" output:
> $ diff upside-down-ascii-inp.xq a.xq
> 12c12
> < for $i in (1 to 31) return $i, fn:string-to-codepoints($m)
> ---
> > for $i in (1 to 31) return 0, fn:string-to-codepoints($m)

Why was $i replaced with 0?

> 20,22c20
> < for $c in fn:string-to-codepoints($s)
> < return
> < fn:codepoints-to-string( $M[$c] )
> ---
> > fn:string-to-codepoints($s) ! fn:codepoints-to-string( $M[.] )
> $
> It seems that $M[.] is the problem, because this modified script does what it should:
> $ diff a.xq b.xq
> 20c20
> < fn:string-to-codepoints($s) ! fn:codepoints-to-string( $M[.] )
> ---
> > fn:string-to-codepoints($s) ! fn:codepoints-to-string( . )
> $
>
> Outputs:
> [ ")4102(", "!raey wen yppah a dna", ",samtsirhC yrreM" ]
>
>
> Can somebody make "Share" work again on try.zorbo.io?
> What is the problem with Xidel's "permalink"?
> Is the $M[.] for map operator a bug in zorba engine?

I think the bug is because the map (actually, a sequence of items) in $M is inverted compared to what you want (it's mapping classical characters to upside-down characters, but you look it up with with an upside-down character).

This seems to work fine:

fn:string-to-codepoints($s) !
fn:codepoints-to-string(
(for $code at $i in $M
where $code eq .
return $i)[1] )

But for efficiency, I think it would be faster to store a map from upside-down characters to classical characters. This will have to be an object though, because the keys will be in a sparse range I guess.

> Where can I find the map operation in JSONiq 1.0 spec?
> (only found it in the JSONiq book)
>

It's in the complete JSONiq spec here:http://www.jsoniq.org/docs/JSONiq/html-single/index.html#idm50777712
But it's not in the JSONiq extension to XQuery spec because it's an XQuery feature already.

I hope it helps?

Kind regards,
Ghislain

her...@stamm-wilbrandt.de

unread,
Dec 21, 2013, 7:59:00 PM12/21/13
to jso...@googlegroups.com
Hi Ghislain,


> Why was $i replaced with 0?
>
because zorba complains on character 1:
dynamic error [err:FOCH0001]: "1": invalid code point

Unfortunately try.zorba.io Share still is broken, can you make somebody fix it?


> I think the bug is because the map (actually, a sequence of items) in $M is inverted compared to what you want
>
No, $M[$i] is defined for code points 1-126 (ascii).
Ascii code $i is mapped to the (unicode) code point of its upside-down character.

So I think
fn:string-to-codepoints($s) ! fn:codepoints-to-string( $M[.] )

should map each character codepoint from $s to its upside-down codepoint.


Becasuse Share does not work, here is the script:


(:declare option jsoniq-version "0.4.42";:)
declare option output:method "json";


declare variable $inp := [ "Merry Christmas,", "and a happy new year!", "(2014)" ];

declare variable $m := fn:string-join( ( " ¡,#$%⅋,)(*+'-˙/0ƖᄅƐㄣϛ9ㄥ86:;>=<¿",
  "@∀qƆpƎℲפHIſʞ˥WNOԀQɹS┴∩ΛMX⅄Z]\[^‾,ɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz}|{~" ), '');

declare variable $M := (

  for $i in (1 to 31) return 0,  fn:string-to-codepoints($m)
);

[
  for $s in fn:reverse( jn:members( $inp ) )
    return
      fn:string-join(
        fn:reverse(

          fn:string-to-codepoints($s) ! fn:codepoints-to-string( $M[.] )
        ),
        ''
      )
]

And this is the output generated by try.zorba.io:
[ " #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~", " #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~", " #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~ #$%*+-/08:;=@HINOQSXZ\\^losxz|~" ]


This script without map operator works well on try.zorba.io:


(:declare option jsoniq-version "0.4.42";:)
declare option output:method "json";


declare variable $inp := [ "Merry Christmas,", "and a happy new year!", "(2014)" ];

declare variable $m := fn:string-join( ( " ¡,#$%⅋,)(*+'-˙/0ƖᄅƐㄣϛ9ㄥ86:;>=<¿",
  "@∀qƆpƎℲפHIſʞ˥WNOԀQɹS┴∩ΛMX⅄Z]\[^‾,ɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz}|{~" ), '');

declare variable $M := (

  for $i in (1 to 31) return $i,  fn:string-to-codepoints($m)
);

[
  for $s in fn:reverse( jn:members( $inp ) )
    return
      fn:string-join(
        fn:reverse(

          for $c in fn:string-to-codepoints($s)
            return
              fn:codepoints-to-string( $M[$c] )
        ),
        ''
      )
]

and produces this output:
[ "(ㄣƖ0ᄅ)", "¡ɹɐǝʎ ʍǝu ʎddɐɥ ɐ puɐ", "'sɐɯʇsᴉɹɥƆ ʎɹɹǝW" ]


Thanks for the spec pointer to the "complete JSONiq spec", I was not aware having to look there.

Hermann.

her...@stamm-wilbrandt.de

unread,
Dec 21, 2013, 8:24:43 PM12/21/13
to jso...@googlegroups.com
Debugged a bit further on minimized script for testing map.

Capital "M" (codepoint 77) gets mapped to lower case "w" (codepoint 87).

$M[.]  should just return 87, but it returns many integers instead.

The additional lines show that ".", ". + 1" and "$M[77]" work fine.

This is minimal script:
declare variable $inp := [ "M" ];

declare variable $m := " ¡,#$%⅋,)(*+'-˙/0ƖᄅƐㄣϛ9ㄥ86:;>=<¿@∀qƆpƎℲפHIſʞ˥WNOԀQɹS┴∩ΛMX⅄Z]ß[^‾,ɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz}|{~";

declare variable $M := ( (1 to 31),  fn:string-to-codepoints($m) );

fn:string-to-codepoints( $inp(1) ) ! .,
fn:string-to-codepoints( $inp(1) ) ! (. + 1),
fn:string-to-codepoints( $inp(1) ) ! $M[.],
$M[77]

It returns:
<?xml version="1.0" encoding="UTF-8"?>
77 78 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 35 36 37 42 43 45 47 48 56 58 59 61 64 72 73 78 79 81 83 88 90 94 108 111 115 120 122 124 126 87

but I think it should return:
<?xml version="1.0" encoding="UTF-8"?>
77 78 87 87


Please let me know if  $M[.]  needs to be written differently, or whether this is a zorba bug.

Hermann.

Matthias Brantner

unread,
Jan 1, 2014, 7:33:37 AM1/1/14
to jso...@googlegroups.com
Hermann

Sorry for the late reply. There is a bug in your minimal script.
The problem is that the context item (.) is re-defined in the
predicate of $M[.]. In this case, . refers to the value of $M
and not the one bound by the ! operator.

Rewriting your script as follows solves the problem:

declare variable $inp := [ "M" ];

declare variable $m := " ¡,#$%⅋,)(*+'-˙/0ƖᄅƐㄣϛ9ㄥ86:;>=<¿@∀qƆpƎℲפHIſʞ˥WNOԀQɹS┴∩ΛMX⅄Z]ß[^‾,ɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz}|{~";

declare variable $M := ( (1 to 31),  fn:string-to-codepoints($m) );

fn:string-to-codepoints( $inp(1) ) ! .,
fn:string-to-codepoints( $inp(1) ) ! (. + 1),
for $i in fn:string-to-codepoints( $inp(1) )
return $M[$i],
$M[77]

HTH

Matthias

--
You received this message because you are subscribed to the Google Groups "JSONiq" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jsoniq+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

her...@stamm-wilbrandt.de

unread,
Jan 2, 2014, 6:59:47 AM1/2/14
to jso...@googlegroups.com
Thanks for the reply, Matthias.

...
Rewriting your script as follows solves the problem:

declare variable $inp := [ "M" ];

declare variable $m := " ¡,#$%⅋,)(*+'-˙/0ƖᄅƐㄣϛ9ㄥ86:;>=<¿@∀qƆpƎℲפHIſʞ˥WNOԀQɹS┴∩ΛMX⅄Z]ß[^‾,ɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz}|{~";

declare variable $M := ( (1 to 31),  fn:string-to-codepoints($m) );

fn:string-to-codepoints( $inp(1) ) ! .,
fn:string-to-codepoints( $inp(1) ) ! (. + 1),
for $i in fn:string-to-codepoints( $inp(1) )
return $M[$i],
$M[77]

...

That leads to minimal solution I posted in another thread already -- without map operatot:
http://try.zorba.io/queries/xquery/rzOwumc480O2jpWkUN/5leagmV4=


As DataPower Compiler Level3 support guy I did work mostly with XSLT the last 6.5 years (XSD&WSDL as well).
My idea now was to use XSLT "current()" function to address the meaning of ".", but that is undefined in XQuery.
Then I came up with this "let" solution working with map "!" operator -- nice!
http://try.zorba.io/queries/xquery/vuRlJq722rdv8QmUSNnEiOOOk6M%3D


Hermann.

William Candillon

unread,
Jan 3, 2014, 9:11:22 AM1/3/14
to jsoniq
Hi Hermann,

We need a query for Valentine's day :)
Like an ascii flower using FLWORs?

her...@stamm-wilbrandt.de

unread,
Jan 19, 2014, 6:34:59 PM1/19/14
to jso...@googlegroups.com
Hi William,

still thinking above Valentine challenge, I stumbled over XQuery in the browser project -- cool:
https://twitter.com/HermannSW/statuses/425047649041928192
http://stamm-wilbrandt.de/xqib/

Hermann.

her...@stamm-wilbrandt.de

unread,
Feb 4, 2014, 1:23:00 PM2/4/14
to jso...@googlegroups.com

> We need a query for Valentine's day :)
> Like an ascii flower using FLWORs?
>
Or .svg?

I did look for "Iterated Function Systems" and rose first:
http://www.isical.ac.in/~malay/Papers/mitra_iete.pdf#page=18

Then I found instructions on how to really draw a rose:
http://www.yourdrawinglessons.com/how-to-draw-a-rose.html

Not sure yet how to turn that instruction into XQuery script ...

Hermann.
Reply all
Reply to author
Forward
0 new messages