2

In Xquery 3.1 I am trying to transform an XML document into a nested map. My xml document $keyworddoc has this structure :

    <category xml:id="KW0003">
        <desc xml:lang="fr">évêque</desc>
        <desc xml:lang="en">bishop</desc>
        <desc xml:lang="de">Bischof</desc>
        <desc xml:lang="es">obispo</desc>
        <desc xml:lang="it">vescovo</desc>
    </category>
    <category xml:id="KW0004">
        <desc xml:lang="fr">sacrement</desc>
        <desc xml:lang="en">sacrament</desc>
        <desc xml:lang="de">Sakrament</desc>
        <desc xml:lang="es">sacramento</desc>
        <desc xml:lang="it">sacramento</desc>
    </category>
    <category xml:id="KW0005">
        <desc xml:lang="fr">messe</desc>
        <desc xml:lang="en">mass</desc>
        <desc xml:lang="de">Messe</desc>
        <desc xml:lang="es">misa</desc>
        <desc xml:lang="it">messa</desc>
    </category>

with the desired map output:

map {
    "KW0003": map {
                  "fr": "évêque",
                  "en": "bishop",
                  "de": "Bischof",
                  "es": "obispo",
                  "it": "vescovo"},
    "KW0004": map {
                  "fr": "sacrement",
                  "en": "sacrament",
                  "de": "Sakrament",
                  "es": "sacramento",
                  "it": "sacramento"},
    "KW0005": map {
                  "fr": "messe",
                  "en": "mass",
                  "de": "Messe",
                  "es": "misa",
                  "it": "messa"},
    }

However, my function:

   let $kwdoc :=  $keyworddoc//tei:category
   return map:merge(for $kw in $kwdoc 
                    return map{$kw/data(@xml:id) : 
                               map:merge(for $desc in $kw 
                                         return map{$desc/data(@xml:lang) : 
                                                    $desc/text()}
                                         )})

produces the following error which suggests that the nested for loop is not "seeing" the variable $kw?:

Expected single value for key, got 0

Perhaps I am going about constructing my first nested map in the wrong way.

edit: Xquery within eXist 5x.

Many thanks in advance.

jbrehr
  • 775
  • 6
  • 19

1 Answers1

4

Since $kw is bound to a single tei:category element at a time, the clause for $desc in $kw iterates over a single-element sequence and just binds the same element to $desc, so it is equivalent to let $desc := $kw in this case.

What you want is to iterate over the tei:desc children of $kw instead:

let $kwdoc := $keyworddoc//tei:category
return map:merge(
  for $kw in $kwdoc 
  return map{
    $kw/data(@xml:id): map:merge(
      for $desc in $kw/tei:desc
      return map{ $desc/data(@xml:lang): $desc/text() }
    )
  }
)
Leo Wörteler
  • 4,191
  • 13
  • 10
  • Bah, that was sloppy of me. But even so, when I copy-paste your changed code I still get the same error. I stripped out all the `map` and `map:merge` functions to assure the data is coming through and it is. It makes me think something else is not right with nesting these functions. – jbrehr Sep 25 '20 at 14:34
  • Which XQuery processor are you using? It works fine for me in BaseX. – Leo Wörteler Sep 25 '20 at 14:36
  • I'm using eXist 5x. – jbrehr Sep 25 '20 at 14:39
  • Works fine for me on eXist-db 5.3.0-SNAPSHOT – adamretter Sep 25 '20 at 14:59
  • 1
    In fact, it works fine, it was a problem when I applied it to the production file which it turns out had certain missing values. It seems I wasn't handling that correctly. – jbrehr Sep 25 '20 at 15:17