joewiz
11/9/2015 - 6:20 PM

Deduplicate a sequence of mixed-content items, with XQuery

Deduplicate a sequence of mixed-content items, with XQuery

<results>
    <item>³c<stress>o</stress>mbine²</item>
    <item>³comb<stress>i</stress>ne²</item>
</results>
xquery version "3.0";

declare namespace functx = "http://www.functx.com";

(: http://www.xqueryfunctions.com/xq/functx_index-of-deep-equal-node.html :)
declare function functx:index-of-deep-equal-node
  ( $nodes as node()* ,
    $nodeToFind as node() )  as xs:integer* {

  for $seq in (1 to count($nodes))
  return $seq[deep-equal($nodes[$seq],$nodeToFind)]
 } ;

declare function local:remove($items, $indexes, $index) {
    if ($index) then
        let $new-items := remove($items, $index)
        return
            local:remove($new-items, tail($indexes), head($indexes))
    else
        $items
};

declare function local:remove($items, $indexes) {
    let $sorted-indexes := 
        for $index in $indexes 
        order by $index descending 
        return $index
    return
        local:remove($items, tail($indexes), head($indexes))
};

declare function local:dedupe($items, $item) {
    let $matches := functx:index-of-deep-equal-node($items, $item)
    return
        if ($matches) then
            let $new-items := local:remove($items, $matches)
            return
                ($item, local:dedupe($items))
        else 
            $item
};

declare function local:dedupe($items) {
    local:dedupe(tail($items), head($items))
};

let $items := 
    (
        <item>³c<stress>o</stress>mbine²</item>,
        <item>³comb<stress>i</stress>ne²</item>,
        <item>³c<stress>o</stress>mbine²</item>
    )
return 
    <results>{ local:dedupe($items) }</results>