Your solution is working but I'd need to run a db:info first to ensure the index is there.
Exactly: If the index may not exist, db:info is a good choice:
let $id := 'f0_36498' for $db in 'factbook' return if(db:info($db)//attrindex = true()) then ( db:attribute($db, $id, 'id')/parent::city ) else ( db:open($db)//city[@id = $id] )
I think I'll try the way of using a query string patched with the db-name and run it through xquery:eval.
That's surely one more choice you have..
let $id := 'f0_36498' for $db in 'factbook' return xquery:eval(" declare variable $db external; declare variable $id external; db:open($db)//city[@id = $id]", map { 'db': $db, 'id': $id } )