I would look at map:for-each()
<https://docs.basex.org/wiki/Map_Module#map:for-each> for this. You may
want to consider an output to an array if you've got multiples of the same
key.
I would suggest chapter 7 of the new book by Joe Wicentowski *XQuery for
Humanists* which covers maps and arrays. Some previews here:
https://xquery.forhumanists.org/
JPR
On Fri, Jan 7, 2022 at 5:19 PM Eliot Kimber ekimber(_at_)contrext(_dot_)com <
xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:
I’m starting to use XQuery again after being away from it for a few years
and also trying to re-learn how to operate on maps efficiently as my
current XQuery use is largely data analysis and reporting over large bodies
of DITA content, so there’s lots of reference management and resolution to
be done, lots of fiddly bits to keep track of.
I ran into a coding bug that threw me for a minute and thought I’d mention
it here just in case it throws anyone else in the future (including future
me).
In my XQuery script I’m building a map from all the image files in a
directory tree (using BaseX’s file extensions):
let $files := file:list($rootDir, true(), ‘*.png’)
let $imageMap := map:merge(
for $file in $files
map:entry(local:getFilename($file), map{‘path’ : $file, ‘keyname’,
local:getKeyName($file))
)
At this point $imageMap is a map where each entry’s value is also a map.
I then iterate over the map to find images not referenced from any topics
in my doc set:
let $orphanMap := map:merge(
for $key in map:keys($imageMap)
order by $key
return
if (local:notReferenced($orphanMap($key)(‘keyname’)))
then $orphanMap($key)
else ()
)
I then report the items in $orphanMap.
When I ran the code as shown I was surprised to only get one item in the
map even though there are 199 orphaned images in my test set.
My bug of course is that I forgot that I have to construct a new map
entry—what the code above does is add the map that is the value of the
entry to the result map. These maps all have the same keys so of course the
default combine behavior results in a single entry in the result map. Doh!
I clearly had it in my head that “$orphanMap($key)” would return the *
*entry** with that key, not the **value** of the entry with that key.
What threw me at first was that the map:merge() worked because it was
being given map entries to merge, just not the right ones. If the values in
the input map had been something else then the map:merge() would have
failed and I’d have immediately realized my mistake.
The correct code is:
let $orphanMap := map:merge(
for $key in map:keys($imageMap)
order by $key
return
if (local:notReferenced($orphanMap($key)(‘keyname’)))
then map:entry($key, $orphanMap($key))
else ()
)
I’m also wondering if there’s any general source of XQuery coding patterns
for working with maps in non-trivial ways? I haven’t run across one but I
haven’t looked too hard yet.
Cheers,
Eliot
--
Eliot Kimber
http://contrext.com
XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/3377836> (by
email <>)
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--