Serializing function types with fn:serialize should default to the adaptive method.
At the moment fn:serialize([1]), fn:serialize(map{1:0}) both return an empty string.
The serialisation to default to the adaptive method.
fn:serialize([1]) => "[1]"fn:serialize(map{1:0}) => "map{1:0}"let $data := (
[1, 2, [1, 2]],
map{"this": "is", "just": ("a", "test")}
)
return fn:serialize($data) eq fn:serialize($data, map {"method": "adaptive"})
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.
Most helpful comment
[1] instance of array(*), [1,2] instance of array(*)returnstrue(), true(), so eXist knows it's an array.The spec for
fn:serializesays: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":
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:
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.