Open line-o opened 5 years ago
I am also wondering what the expected behaviour for maps is. BaseX just throws an error while existdb will return an empty string again. When I have time to look at the spec I might expand this issue.
Same behaviour applies to util:log("debug", [1,2])
maybe in fn:serialize([1])
the [1] is seen as a predicate.....
saxon returns "1" anyway
[1] instance of array(*), [1,2] instance of array(*)
returns true(), true()
, so eXist knows it's an array.
The spec for fn:serialize
says:
If the second argument is omitted, or is supplied in the form of an output:serialization-parameters element, then the values of any serialization parameters that are not explicitly specified is ·implementation-defined·, and may depend on the context.
This leads to the question, what is eXist's default set of serialization parameters?
If, however, we supply a serialization method, then eXist should respect it. Let's try "text":
xquery version "3.1";
serialize([1], map {"method": "text"})
This also returns "". Thus I think we have a serialization bug. The relevant portion of the spec is https://www.w3.org/TR/xslt-xquery-serialization-31/#serdm, which states:
Each item in the sequence that is an array is flattened by calling the function
array:flatten()
before being copied.
If we do this manually (via serialize(array:flatten([1]))
, we get the expected result, "1".
In other words, eXist is failing to flatten arrays during sequence normalization.
Thanks @joewiz for your thorough investigation of the issue. I already learned a lot.
One thing keeps bugging me:
array:flatten([1])
should yield [1]
and thus both should be identical.
To me array:flatten
would only be necessary for nested arrays (serialize([1, [2, 3]])
).
The outcome 1 2 3
would also not meet my expectations. If the spec says so for text then I would argue that exist should use JSON as the default.
When serializing maps
xquery version "3.1";
let $m := map{"key":"1"}
return (
serialize($m),
serialize($m, map{'method':'text'}),
serialize($m, map{'method':'json'}),
serialize($m, map{'method':'xml'})
)
(: yields ("", "", "{\"key\": \"1\"}", "") :)
Only JSON serialisation does return the expected output.
Digging a little deeper I found that there is an 'adaptive' method which does things as one would expect
xquery version "3.1";
let $m := (map {"key":"1"}, [1, [2, 3]])
return (
serialize($m),
serialize($m, map {'method':'adaptive'}),
serialize($m, map {'method':'text'}),
serialize($m, map {'method':'json'}),
serialize($m, map {'method':'xml'})
)
Just read the spec for array:flatten
to learn that is indeed a function that returns a sequence of all members of nested arrays.
This problem still affects eXist 5.2.0.
What is the problem
Serializing function types with
fn:serialize
should default to the adaptive method. At the momentfn:serialize([1])
,fn:serialize(map{1:0})
both return an empty string.What did you expect
The serialisation to default to the adaptive method.
fn:serialize([1])
=>"[1]"
fn:serialize(map{1:0})
=>"map{1:0}"
Describe how to reproduce or add a test
Context information