Error: Stack Overflow: Try tail recursion? Compiling: - flatten nested single iter path: * - rewrite iter filter to iter path: $in_2[*] -> $in_2/* - remove type check: xs:string -> (if($in_2 instance of element()) then concat("{", name($in_2), (if($in_2/*) then string-join($in_2/* ! Q{https://precisioncontent.com/xquery/analysis/for-reuse}getStruct(.)) else ()), "}") else error(... - merge: concat(base-uri($in_1), replace(path($in_1), "Q\{\}", "")) - rewrite mixed path to fn:concat(value1,value2[,...]): $in_1/concat(base-uri($in_1), replace(path($in_1), "Q\{\}", "")) -> concat(base-uri($in_1), replace(path($in_1), "Q\{\}", "")) - remove type check: xs:string -> concat(base-uri($in_1), replace(path($in_1), "Q\{\}", "")) - inline for $key_4 in map:keys($map_3) - simplify FLWOR expression: map:keys($map_3) ! map:entry($map_3(.), .) - remove type check: map(xs:anyAtomicType, xs:anyAtomicType) -> map:merge(map:keys($map_3) ! map:entry($map_3(.), .)) - remove type check: $do_8 as xs:string - rewrite 'eq' comparison to simplified = comparison: ($do_8 eq "{") -> ($do_8 = "{") - swap operands: (if(normalize-space($do_8)) then (if(($do_8 = "{")) then (concat("<", head($names_5), ">"), Q{https://precisioncontent.com/xquery/analysis/for-reuse}tag(tail($names_5), (head($names_5), $active_6), su... - inline $reuse:NMToken - rewrite mixed path to iterative dual simple map: $chunked_10/fn:match/string() -> $chunked_10/fn:match ! string() - remove type check: $openClose_12 as xs:string+ - inline let $openClose_12 := string-join($chunked_10/fn:non-match) - inline let $names_11 as xs:string+ := $chunked_10/fn:match ! string() - inline let $chunked_10 as element(fn:analyze-string-result) := analyze-string($in_9, "[\p{L}\p{Nd}._\-:]+") - simplify FLWOR expression: (analyze-string($in_9, "[\p{L}\p{Nd}._\-:]+") treat as element(fn:analyze-string-result)) ! string-join(Q{https://precisioncontent.com/xquery/analysis/for-reuse}tag((fn:match ! string() treat as xs:st... - remove type check: xs:string -> (analyze-string($in_9, "[\p{L}\p{Nd}._\-:]+") treat as element(fn:analyze-string-result)) ! string-join(Q{https://precisioncontent.com/xquery/analysis/for-reuse}tag((fn:match ! string() treat as xs:st... - remove type check: xs:string -> replace($in_14, "Q\{\}", "") - inline Q{https://precisioncontent.com/xquery/analysis/for-reuse}scrubPath#1 - remove type check: $in_34 as xs:string - inline let $in_34 := $in_13 - simplify FLWOR expression: replace($in_13, "Q\{\}", "") - remove type check: xs:string -> replace(replace($in_13, "Q\{\}", ""), "\[\p{Nd}+\]", "") - rewrite cached filter to util:last(items): tokenize($path_15, "/")[last()] -> util:last(tokenize($path_15, "/")) - inline Q{https://precisioncontent.com/xquery/analysis/for-reuse}scrubName#1 - inline let $in_35 as xs:string := util:last(tokenize($path_15, "/")) - simplify FLWOR expression: replace(replace((util:last(tokenize($path_15, "/")) promote to xs:string), "Q\{\}", ""), "\[\p{Nd}+\]", "") - remove type check: xs:string -> replace(replace((util:last(tokenize($path_15, "/")) promote to xs:string), "Q\{\}", ""), "\[\p{Nd}+\]", "") - inline Q{https://precisioncontent.com/xquery/analysis/for-reuse}getName#1 - remove type check: $path_36 as xs:string - inline let $path_36 := $in_16 - simplify FLWOR expression: replace(replace((util:last(tokenize($in_16, "/")) promote to xs:string), "Q\{\}", ""), "\[\p{Nd}+\]", "") - inline Q{https://precisioncontent.com/xquery/analysis/for-reuse}scrubPath#1 - remove type check: $in_37 as xs:string - inline let $in_37 := $in_16 - simplify FLWOR expression: replace($in_16, "Q\{\}", "") - remove type check: element(element-info) -> { replace(replace((util:last(tokenize($in_16, "/")) promote to xs:string), "Q\{\}", ""), "\[\p{Nd}+\]", "") } { replace($in_16, "Q\{\}", "") } (db:open-pre("data", 0), ...) - rewrite cached filter to iter path: (db:open-pre("data", 0), ...)[ends-with(document-uri(), ".xml")] -> (db:open-pre("data", 0), ...)/.[ends-with(document-uri(), ".xml")] - rewrite list to xs:string sequence: ("block", "defblock", "fnblock", "primaryblock", "regblock", "subblock") -> ("block", "defblock", "fnblock", "primaryblock", ...) - remove type check: $interesting_19 as xs:string+ - remove type check: $pattern_22 as xs:string - inline Q{https://precisioncontent.com/xquery/analysis/for-reuse}getLocation#1 - remove type check: $in_38 as element() - inline let $in_38 := . - simplify FLWOR expression: concat(base-uri(.), replace(path(.), "Q\{\}", "")) - remove type check: $index_27 as xs:integer - remove type check: $type2patternMap_25 as map(xs:string, xs:string) - inline Q{https://precisioncontent.com/xquery/analysis/for-reuse}invertSimpleMap#1 - remove type check: $map_39 as map(xs:anyAtomicType, xs:anyAtomicType) - inline let $map_39 := $type2patternMap_25 - simplify FLWOR expression: map:merge(map:keys($type2patternMap_25) ! map:entry($type2patternMap_25(.), .)) - rewrite lookup to util:map-values(map): $map_30? * -> util:map-values($map_30) - inline for $map_30 in $rawPatterns_20 - simplify FLWOR expression: $rawPatterns_20 ! map:entry($pattern2typeMap_28(map:keys(.)), util:map-values(.)) - remove type check: $found_33 as xs:integer - inline Q{https://precisioncontent.com/xquery/analysis/for-reuse}emitPattern#1 - inline let $in_40 as xs:string := $type2patternMap_25($sp_31) - simplify FLWOR expression: (analyze-string(($type2patternMap_25($sp_31) promote to xs:string), "[\p{L}\p{Nd}._\-:]+") treat as element(fn:analyze-string-result)) ! string-join(Q{https://precisioncontent.com/xquery/analysis/for-... - inline Q{https://precisioncontent.com/xquery/analysis/for-reuse}emitLocation#1 - remove type check: $in_41 as xs:string - inline let $in_41 := . - simplify FLWOR expression: { replace(replace((util:last(tokenize(., "/")) promote to xs:string), "Q\{\}", ""), "\[\p{Nd}+\]", "") } { replace(., "Q\{\}", "") } - inline let $type2locationMap_29 as map(xs:string, xs:string+) := map:merge($rawPatterns_20 ! map:entry($pattern2typeMap_28(map:keys(.)), util:map-values(.))) - inline let $interesting_19 := ("block", "defblock", "fnblock", "primaryblock", ...) - inline let $DITAcontentSet_18 as document-node()+ := (db:open-pre("data", 0), ...)/.[ends-with(document-uri(), ".xml")] - remove type check: $in_2 as element()? - remove type check: $in_1 as element() - remove type check: $map_3 as map(xs:anyAtomicType, xs:anyAtomicType) - remove type check: $names_5 as xs:string* - remove type check: $active_6 as xs:string* - remove type check: $event_7 as xs:string* - remove type check: $in_14 as xs:string - remove type check: $in_16 as xs:string Optimized Query: declare function Q{https://precisioncontent.com/xquery/analysis/for-reuse}getStruct($in_2) { (if($in_2 instance of element()) then concat("{", name($in_2), (if($in_2/*) then string-join($in_2/* ! Q{https://precisioncontent.com/xquery/analysis/for-reuse}getStruct(.)) else ()), "}") else error(Q{http://www.w3.org/2005/xqt-errors}XPTY0004, "Cannot promote empty-sequence() to xs:string: ().")) }; declare function Q{https://precisioncontent.com/xquery/analysis/for-reuse}tag($names_5, $active_6, $event_7) { (let $do_8 := substring($event_7, 1, 1) where normalize-space($do_8) return (if(($do_8 = "{")) then (concat("<", head($names_5), ">"), Q{https://precisioncontent.com/xquery/analysis/for-reuse}tag(tail($names_5), (head($names_5), $active_6), substring($event_7, 2))) else (concat(""), Q{https://precisioncontent.com/xquery/analysis/for-reuse}tag($names_5, tail($active_6), substring($event_7, 2))))) }; (let $rawPatterns_20 as (map(xs:string, xs:string+))+ := (for $list_21 in ((db:open-pre("data", 0), ...)/.[ends-with(document-uri(), ".xml")] treat as document-node()+)/descendant::*[(name() = ("block", "defblock", "fnblock", "primaryblock", ...))] let $pattern_22 := Q{https://precisioncontent.com/xquery/analysis/for-reuse}getStruct($list_21) let (: post-group :) $list_24 := $list_21 group by $pattern_23 := $pattern_22 return map:entry($pattern_23, $list_24 ! concat(base-uri(.), replace(path(.), "Q\{\}", "")))) let $type2patternMap_25 := map:merge((for $pattern_26 at $index_27 in $rawPatterns_20 ! map:keys(.) order by $pattern_26 empty least return map:entry(concat("type", $index_27), $pattern_26))) let $pattern2typeMap_28 as map(xs:string, xs:string) := map:merge(map:keys($type2patternMap_25) ! map:entry($type2patternMap_25(.), .)) return (map:merge($rawPatterns_20 ! map:entry($pattern2typeMap_28(map:keys(.)), util:map-values(.))) treat as map(xs:string, xs:string+)) ! { (for $sp_31 in map:keys(.) let $locations_32 as xs:string+ := .($sp_31) let $found_33 := count($locations_32) order by $found_33 descending empty least return { $sp_31 } { (analyze-string(($type2patternMap_25($sp_31) promote to xs:string), "[\p{L}\p{Nd}._\-:]+") treat as element(fn:analyze-string-result)) ! string-join(Q{https://precisioncontent.com/xquery/analysis/for-reuse}tag((fn:match ! string() treat as xs:string+), (), string-join(fn:non-match))) } { $locations_32 ! { replace(replace((util:last(tokenize(., "/")) promote to xs:string), "Q\{\}", ""), "\[\p{Nd}+\]", "") } { replace(., "Q\{\}", "") } }) }) Query: import module namespace reuse = "https://precisioncontent.com/xquery/analysis/for-reuse" at 'EG-structure-compare.xqm'; let $DITAcontentSet as document-node()+ := db:open('data')[ends-with(document-uri(),'.xml')] let $interesting as xs:string+ := ('block','defblock','fnblock','primaryblock','regblock','subblock') let $rawPatterns as map(xs:string,xs:string+)+ := for $list in $DITAcontentSet/descendant::*[name() = $interesting] let $pattern as xs:string := reuse:getStruct($list) group by $pattern return map:entry($pattern, $list ! reuse:getLocation(.)) let $type2patternMap as map(xs:string,xs:string) := map:merge( for $pattern at $index in $rawPatterns ! map:keys(.) order by $pattern return map:entry(concat('type',$index),$pattern) ) let $pattern2typeMap as map(xs:string,xs:string) := reuse:invertSimpleMap($type2patternMap) let $type2locationMap as map(xs:string,xs:string+) := map:merge( for $map in $rawPatterns return map:entry($pattern2typeMap(map:keys($map)),$map?*) ) return { for $sp in map:keys($type2locationMap) let $locations as xs:string+ := $type2locationMap($sp) let $found as xs:integer := count($locations) order by $found descending return {$sp} {reuse:emitPattern($type2patternMap($sp))} {$locations ! reuse:emitLocation(.)} } Query Plan: { } err:XPTY0004 Cannot promote empty-sequence() to xs:string: (). 1 1 { < > 2 </ > 2 .xml block defblock fnblock primaryblock regblock Q\{\} type structure-patterns pattern number-found designation pattern [\p{L}\p{Nd}._\-:]+ locations element-info name / Q\{\} \[\p{Nd}+\] location Q\{\}