Hello all, I want to dynamically build a map where the value is an array of maps. I am having a problem with the syntax. (My use-case is to deliver this as JSON for simple ingestion to Spark, by the way).
Here's my test code, which translates cleanly into JSON:
declare option output:method 'json'; map { "authors": [ map{"fn":"John", "ln":"Smith"}, map{"fn":"Jane", "ln":"Doe"} ] }
However, when I try to build the same map dynamically, I get the error "Value has more than one item". I guess this is because my for loop is returning a sequence, but I can't figure out the syntax to get it working. Any ideas?
declare option output:method 'json'; map { "authors": [ (for $b in $authors return (: just assume $authors is populated ...:) map{"fn":$b/*:given-name/text(), "ln":$b/*:surname/text()}) ] }
TIA!
________________________________
Elsevier B.V. Registered Office: Radarweg 29, 1043 NX Amsterdam, The Netherlands, Registration No. 33156677, Registered in The Netherlands.
Hi Christian,
I was already kicking myself for rushing and not providing a SCE! Please see the code below, and thanks.
declare option output:method 'json';
declare variable $authors := <authors>
<author>
<given-name>Robert A</given-name>
<surname>Sanders</surname>
</author>
<author>
<given-name>Emily</given-name>
<surname>Chapel</surname>
</author>
</authors>;
map {
"authors": [
(for $b in $authors/author return
map{"fn":$b/*:given-name/text(), "ln":$b/*:surname/text()})
]
}
-----Original Message----- From: Christian Grün [mailto:christian.gruen@gmail.com] Sent: 12 December 2017 13:20 To: Hondros, Constantine (ELS-AMS) Cc: basex-talk@mailman.uni-konstanz.de Subject: Re: [basex-talk] XQuery 3.1/Build array of maps dynamically
*** External email: use caution ***
Hi Constantine,
(: just assume $authors is populated ...:)
Could you provide us with a little self-contained example? Because there are all kinds of populations out there.
TIA as well,
Christian
________________________________
Elsevier B.V. Registered Office: Radarweg 29, 1043 NX Amsterdam, The Netherlands, Registration No. 33156677, Registered in The Netherlands.
Thanks. Your query does not yield “Value has more than one item”, at least with the latest snapshot of BaseX. But maybe you are expecting another result?
On Tue, Dec 12, 2017 at 1:30 PM, Hondros, Constantine (ELS-AMS) C.Hondros@elsevier.com wrote:
Hi Christian,
I was already kicking myself for rushing and not providing a SCE! Please see the code below, and thanks.
declare option output:method 'json';
declare variable $authors := <authors>
<author> <given-name>Robert A</given-name> <surname>Sanders</surname> </author> <author> <given-name>Emily</given-name> <surname>Chapel</surname> </author>
</authors>;
map {
"authors": [ (for $b in $authors/author return map{"fn":$b/*:given-name/text(), "ln":$b/*:surname/text()}) ]
}
-----Original Message----- From: Christian Grün [mailto:christian.gruen@gmail.com] Sent: 12 December 2017 13:20 To: Hondros, Constantine (ELS-AMS) Cc: basex-talk@mailman.uni-konstanz.de Subject: Re: [basex-talk] XQuery 3.1/Build array of maps dynamically
*** External email: use caution ***
Hi Constantine,
(: just assume $authors is populated ...:)
Could you provide us with a little self-contained example? Because there are all kinds of populations out there.
TIA as well,
Christian
Elsevier B.V. Registered Office: Radarweg 29, 1043 NX Amsterdam, The Netherlands, Registration No. 33156677, Registered in The Netherlands.
This time I was too quick, sorry (I ignored the query prolog of your query).
This is the fixed version:
declare namespace output = 'http://www.w3.org/2010/xslt-xquery-serialization'; declare option output:method 'json';
declare variable $authors := <authors> <author> <given-name>Robert A</given-name> <surname>Sanders</surname> </author> <author> <given-name>Emily</given-name> <surname>Chapel</surname> </author> </authors>;
map { "authors": array { for $b in $authors/author return map { "fn": $b/*:given-name/text(), "ln": $b/*:surname/text() } } }
Check out [1] to learn about the subtle difference betwen [] and array {}.
Best, Christian
[1] http://docs.basex.org/wiki/XQuery_3.1#Arrays
On Tue, Dec 12, 2017 at 1:32 PM, Christian Grün christian.gruen@gmail.com wrote:
Thanks. Your query does not yield “Value has more than one item”, at least with the latest snapshot of BaseX. But maybe you are expecting another result?
On Tue, Dec 12, 2017 at 1:30 PM, Hondros, Constantine (ELS-AMS) C.Hondros@elsevier.com wrote:
Hi Christian,
I was already kicking myself for rushing and not providing a SCE! Please see the code below, and thanks.
declare option output:method 'json';
declare variable $authors := <authors>
<author> <given-name>Robert A</given-name> <surname>Sanders</surname> </author> <author> <given-name>Emily</given-name> <surname>Chapel</surname> </author>
</authors>;
map {
"authors": [ (for $b in $authors/author return map{"fn":$b/*:given-name/text(), "ln":$b/*:surname/text()}) ]
}
-----Original Message----- From: Christian Grün [mailto:christian.gruen@gmail.com] Sent: 12 December 2017 13:20 To: Hondros, Constantine (ELS-AMS) Cc: basex-talk@mailman.uni-konstanz.de Subject: Re: [basex-talk] XQuery 3.1/Build array of maps dynamically
*** External email: use caution ***
Hi Constantine,
(: just assume $authors is populated ...:)
Could you provide us with a little self-contained example? Because there are all kinds of populations out there.
TIA as well,
Christian
Elsevier B.V. Registered Office: Radarweg 29, 1043 NX Amsterdam, The Netherlands, Registration No. 33156677, Registered in The Netherlands.
Ah, fantastic. Thank you Christian (and Martin).
Yes, I was using an incorrect constructor for Arrays in this instance.
Many thanks, Constantine
-----Original Message----- From: Christian Grün [mailto:christian.gruen@gmail.com] Sent: 12 December 2017 13:41 To: Hondros, Constantine (ELS-AMS) Cc: basex-talk@mailman.uni-konstanz.de Subject: Re: [basex-talk] XQuery 3.1/Build array of maps dynamically
*** External email: use caution ***
This time I was too quick, sorry (I ignored the query prolog of your query).
This is the fixed version:
declare namespace output = 'http://www.w3.org/2010/xslt-xquery-serialization'; declare option output:method 'json';
declare variable $authors := <authors> <author> <given-name>Robert A</given-name> <surname>Sanders</surname> </author> <author> <given-name>Emily</given-name> <surname>Chapel</surname> </author> </authors>;
map { "authors": array { for $b in $authors/author return map { "fn": $b/*:given-name/text(), "ln": $b/*:surname/text() } } }
Check out [1] to learn about the subtle difference betwen [] and array {}.
Best, Christian
[1] http://docs.basex.org/wiki/XQuery_3.1#Arrays
On Tue, Dec 12, 2017 at 1:32 PM, Christian Grün christian.gruen@gmail.com wrote:
Thanks. Your query does not yield “Value has more than one item”, at least with the latest snapshot of BaseX. But maybe you are expecting another result?
On Tue, Dec 12, 2017 at 1:30 PM, Hondros, Constantine (ELS-AMS) C.Hondros@elsevier.com wrote:
Hi Christian,
I was already kicking myself for rushing and not providing a SCE! Please see the code below, and thanks.
declare option output:method 'json';
declare variable $authors := <authors>
<author> <given-name>Robert A</given-name> <surname>Sanders</surname> </author> <author> <given-name>Emily</given-name> <surname>Chapel</surname> </author>
</authors>;
map {
"authors": [ (for $b in $authors/author return map{"fn":$b/*:given-name/text(), "ln":$b/*:surname/text()}) ]
}
-----Original Message----- From: Christian Grün [mailto:christian.gruen@gmail.com] Sent: 12 December 2017 13:20 To: Hondros, Constantine (ELS-AMS) Cc: basex-talk@mailman.uni-konstanz.de Subject: Re: [basex-talk] XQuery 3.1/Build array of maps dynamically
*** External email: use caution ***
Hi Constantine,
(: just assume $authors is populated ...:)
Could you provide us with a little self-contained example? Because there are all kinds of populations out there.
TIA as well,
Christian
Elsevier B.V. Registered Office: Radarweg 29, 1043 NX Amsterdam, The Netherlands, Registration No. 33156677, Registered in The Netherlands.
________________________________
Elsevier B.V. Registered Office: Radarweg 29, 1043 NX Amsterdam, The Netherlands, Registration No. 33156677, Registered in The Netherlands.
On 12.12.2017 13:30, Hondros, Constantine (ELS-AMS) wrote:
I was already kicking myself for rushing and not providing a SCE! Please see the code below, and thanks.
declare option output:method 'json';
declare variable $authors := <authors>
<author>
<given-name>Robert A</given-name>
<surname>Sanders</surname>
</author>
<author>
<given-name>Emily</given-name>
<surname>Chapel</surname>
</author>
</authors>;
map {
"authors": [
(for $b in $authors/author return
map{"fn":$b/*:given-name/text(), "ln":$b/*:surname/text()})
]
}
I think to get the map structure from your earlier sample you want
declare option output:method 'json';
declare variable $authors := <authors>
<author>
<given-name>Robert A</given-name>
<surname>Sanders</surname>
</author>
<author>
<given-name>Emily</given-name>
<surname>Chapel</surname>
</author>
</authors>;
map {
"authors": array{$authors/author!map{"fn" : data(given-name), "ln" : data(surname)}}
}
Result is
{ "authors": [ { "ln": "Sanders", "fn": "Robert A" }, { "ln": "Chapel", "fn": "Emily" } ] }
basex-talk@mailman.uni-konstanz.de