declare namespace fun = 'have.more.fun'; declare function fun:closure($input as node()*, $result as node()*) as node()* { let $current := $input/idref(.)[name() = "from"]/../@to let $new := $current except $result let $all := ($result,$new) return if(exists($new)) then ($new, fun:closure($new,$all)) else () }; doc()//category[@id="category0"]/@id/fun:closure(.,())/id(.)/name