From: Adam R. <ad...@ex...> - 2016-11-28 18:24:39
|
I thought I would just post this script as it might be useful to others who need to perform recursive operations on the database structure. For example, you could use this to recursively apply an ACL to a Collection Hierarchy, or even to do some sort of transformation. xquery version "3.0"; (:~ : Given a collection, this function recursively descends through : all sub-collections and sub-resources : applying the function $collection-function to each collection : and $resource-function to each resource : : @param collection-function A functuon that accepts a path to a collection : @param resource-function A function that accepts a path to a resource : : @return The sequence of the results from ($collection-function, $resource-function*)* : recursively descending :) declare function local:descend($collection-path as xs:string, $collection-function as function(xs:string) as item()*, $resource-function as function(xs:string) as item()*) { $collection-function($collection-path) , xmldb:get-child-resources($collection-path) ! $resource-function($collection-path || "/" || .) , xmldb:get-child-collections($collection-path) ! local:descend($collection-path || "/" || ., $collection-function, $resource-function) }; (:~ : Given a collection it returns the parent collection or the empty sequence : if we are already at the database root (i.e. /db) : : @param A path to a collection : : @return The path to the parent collection, or the empty sequence if there : is no parent collection :) declare function local:parent-collection($collection-path as xs:string) as xs:string? { let $parent-collection-path := replace($collection-path, "(/.+)/.*", "$1") return if($parent-collection-path eq $collection-path or not(starts-with($parent-collection-path, "/db"))) then () else $parent-collection-path }; (:~ : Given a collection, this function recursively acends through : all ancestror collections (including the given collection) and : resources applying the function $collection-function to each : collection and $resource-function to each resource : : @param collection-function A functuon that accepts a path to a collection : @param resource-function A function that accepts a path to a resource : : @return The sequence of the results from ($collection-function, $resource-function*)* : recursively ascending :) declare function local:ascend($collection-path as xs:string, $collection-function as function(xs:string) as item()*, $resource-function as function(xs:string) as item()*) { if(not(starts-with($collection-path, "/db"))) then () else $collection-function($collection-path) , xmldb:get-child-resources($collection-path) ! $resource-function( $collection-path || "/" || .) , local:parent-collection($collection-path) ! local:ascend(., $collection-function, $resource-function) }; Once such example of using this is to remove all guest access permissions to EVERYTHING in the database: declare function local:remove-all-guest-access($root-collection-path as xs:string) { let $remove-guest-access := function($path) { sm:chmod(xs:anyURI($path), "o-r,o-w,o-x,o-s,o-t") } return local:descend($root-collection-path, $remove-guest-access, $remove-guest-access) }; local:remove-all-guest-access("/db") Enjoy! Adam. -- Adam Retter eXist Developer { United Kingdom } ad...@ex... irc://irc.freenode.net/existdb |