[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Subtle (or not?) Map Processing Bug in XQuery
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 <>)
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|