Re: [xsl] Subtle (or not?) Map Processing Bug in XQuery

Subject: Re: [xsl] Subtle (or not?) Map Processing Bug in XQuery
From: "Jean-Paul Rehr rehrjb@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 7 Jan 2022 17:13:03 -0000
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@xxxxxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> Ibm 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 therebs 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 Ibd
mention
> it here just in case it throws anyone else in the future (including future
> me).
>
>
>
> In my XQuery script Ibm building a map from all the image files in a
> directory tree (using BaseXbs file extensions):
>
>
>
> let $files := file:list($rootDir, true(), b*.pngb)
>
> let $imageMap := map:merge(
> for $file in $files
>
> map:entry(local:getFilename($file), map{bpathb : $file, bkeynameb,
> local:getKeyName($file))
>
> )
>
>
>
> At this point $imageMap is a map where each entrybs 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)(bkeynameb)))
>
> 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
> entrybwhat 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 b$orphanMap($key)b 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 Ibd 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)(bkeynameb)))
>
> then map:entry($key, $orphanMap($key))
>
> else ()
>
> )
>
>
>
> Ibm also wondering if therebs any general source of XQuery coding
patterns
> for working with maps in non-trivial ways? I havenbt run across one but I
> havenbt 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 <>)

Current Thread