Test Results for Collate

eXist Version 1.4.0 : Revision 10440

6 Tests passed

Examples of Collating sequences.

Author: Chris Wallace

Iterative merge of primary and secondary sequences : Passed

Task where one sequence is the primary seqence, one could iterate through that sequence and look up in the secondary.
XQuery
 
declare  function local:merge($primary, $secondary as item()* ) as item()*  {
for $item in $primary
return
    if (exists($secondary[.=$item]))
    then <matched>{$item}</matched>
    else <missing>{$item}</missing>
};

let $a := 
<list>
   <item>a</item>
   <item>b</item>
   <item>c</item>
   <item>d</item>
   <item>g</item>
   <item>j</item>
</list>

let $b := 
<list>
   <item>b</item>
   <item>e</item>
   <item>h</item>
   <item>j</item>
   <item>k</item>
</list>
return local:merge($a/item,$b/item)      

   
Output
<missing>
    <item>a</item>
</missing>
<matched>
    <item>b</item>
</matched>
<missing>
    <item>c</item>
</missing>
<missing>
    <item>d</item>
</missing>
<missing>
    <item>g</item>
</missing>
<matched>
    <item>j</item>
</matched>
Elapsed Time (ms) 13

iterative merge of main and secondary : Passed

Task We could test using a qualified expression.
XQuery
 
declare  function local:merge($primary, $secondary as item()* ) as item()*  {
for $item1 in $primary
return
    if (some $item2 in $secondary satisfies $item2 = $item1)
    then <matched>{$item1}</matched>
    else <missing>{$item1}</missing>
};

let $a := 
<list>
   <item>a</item>
   <item>b</item>
   <item>c</item>
   <item>d</item>
   <item>g</item>
   <item>j</item>
</list>

let $b := 
<list>
   <item>b</item>
   <item>e</item>
   <item>h</item>
   <item>j</item>
   <item>k</item>
</list>
return local:merge($a/item,$b/item)      

   
Output
<missing>
    <item>a</item>
</missing>
<matched>
    <item>b</item>
</matched>
<missing>
    <item>c</item>
</missing>
<missing>
    <item>d</item>
</missing>
<missing>
    <item>g</item>
</missing>
<matched>
    <item>j</item>
</matched>
Elapsed Time (ms) 13

Compare both sequences : Passed

Task The merged sequences can be reversed to provide a symetric comparison
XQuery
 
declare  function local:merge($primary, $secondary as item()* ) as item()*  {
for $item1 in $primary
return
    if (some $item2 in $secondary satisfies $item2 = $item1)
    then <matched>{$item1}</matched>
    else <missing>{$item1}</missing>
};

let $a := 
<list>
   <item>a</item>
   <item>b</item>
   <item>c</item>
   <item>d</item>
   <item>g</item>
   <item>j</item>
</list>

let $b := 
<list>
   <item>b</item>
   <item>e</item>
   <item>h</item>
   <item>j</item>
   <item>k</item>
</list>
return
<result>
   <ab>
   {local:merge($a/item,$b/item)}
   </ab>
   <ba>
   {local:merge($b/item,$a/item) }
  </ba>
</result>
   
Output
<result>
    <ab>
        <missing>
            <item>a</item>
        </missing>
        <matched>
            <item>b</item>
        </matched>
        <missing>
            <item>c</item>
        </missing>
        <missing>
            <item>d</item>
        </missing>
        <missing>
            <item>g</item>
        </missing>
        <matched>
            <item>j</item>
        </matched>
    </ab>
    <ba>
        <matched>
            <item>b</item>
        </matched>
        <missing>
            <item>e</item>
        </missing>
        <missing>
            <item>h</item>
        </missing>
        <matched>
            <item>j</item>
        </matched>
        <missing>
            <item>k</item>
        </missing>
    </ba>
</result>
Elapsed Time (ms) 16

Recursive merge of a sequence of elements. : Passed

Task The elements are assumed to be in ascending order.
XQuery
 
declare function local:merge($a, $b  as item()*  )  as item()* {
    if (empty($a) and empty($b))
    then ()
    else if (empty ($b) or $a[1] lt $b[1])
    then (<a>{$a[1]}</a>, local:merge(subsequence($a, 2), $b))
    else  if (empty($a) or $a[1] gt $b[1])
    then  (<b>{$b[1]}</b>, local:merge($a, subsequence($b,2)))           
    else   (<match>{$a[1]}</match>,local:merge(subsequence($a,2), subsequence($b,2)))
   };
   
let $a := 
<list>
   <item>a</item>
   <item>b</item>
   <item>c</item>
   <item>d</item>
   <item>g</item>
   <item>j</item>
</list>

let $b := 
<list>
   <item>b</item>
   <item>e</item>
   <item>h</item>
   <item>j</item>
   <item>k</item>
</list>
return local:merge($a/item,$b/item)      

   
Output
<a>
    <item>a</item>
</a>
<match>
    <item>b</item>
</match>
<a>
    <item>c</item>
</a>
<a>
    <item>d</item>
</a>
<b>
    <item>e</item>
</b>
<a>
    <item>g</item>
</a>
<b>
    <item>h</item>
</b>
<match>
    <item>j</item>
</match>
<b>
    <item>k</item>
</b>
Elapsed Time (ms) 24

Generating an update list : Passed

Task If the elements represent files in a file system and have dataTime attributes , we can use this algorithm to generate a list of update actions. Here the items are merely wrapped in a div to carry the update tags. Sample data taken from the Wikibook article
XQuery
 
declare function local:time-merge($a, $b  as item()*  )  as item()* {
    if (empty($a) and empty($b))
    then ()
    else  if (empty ($b) or $a[1] lt $b[1])
    then  (<div class="add">{$a[1]}</div>, local:time-merge(subsequence($a, 2), $b))
    else  if (empty($a) or $a[1] gt $b[1])
    then  (<div class="delete">{$b[1]}</div>,local:time-merge($a, subsequence($b,2)))          
    else   (<div  class="{ if (xs:dateTime($a[1]/@dateTime) gt xs:dateTime($b[1]/@dateTime)) 
                                         then "newer" 
                                         else "older"}"> 
                      {$a[1]}
                </div>,
                 local:time-merge(subsequence($a,2), subsequence($b,2))
               )
   };

let $list1 :=
<list>
   <item dateTime="2009-06-01T11:59:00.000-05:00">apples</item>
   <item dateTime="2009-02-01T11:59:00.000-05:00">bananas</item>
   <item dateTime="2009-02-01T11:59:00.000-05:00">cabbage</item>
  <item dateTime="2009-02-01T11:59:00.000-05:00">carrots</item>
    <item dateTime="2009-02-01T11:59:00.000-05:00">eggplant</item>
   <item dateTime="2009-02-01T11:59:00.000-05:00">grapes</item>
 </list>
 
let $list2 :=
<list>
   <item dateTime="2009-01-01T11:59:00.000-05:00">apples</item>
   <item dateTime="2009-02-01T11:59:00.000-05:00">bananas</item>
   <item dateTime="2009-03-01T11:59:00.000-05:00">carrots</item>
   <item dateTime="2009-02-01T11:58:00.000-05:00">eggplant</item>
   <item dateTime="2009-02-01T12:00:00.000-05:00">grapes</item>
   <item dateTime="2009-04-01T11:59:00.000-05:00">oranges</item>
</list>

return   local:time-merge($list1/item, $list2/item) 

   
Output
<div class="newer">
    <item dateTime="2009-06-01T11:59:00.000-05:00">apples</item>
</div>
<div class="older">
    <item dateTime="2009-02-01T11:59:00.000-05:00">bananas</item>
</div>
<div class="add">
    <item dateTime="2009-02-01T11:59:00.000-05:00">cabbage</item>
</div>
<div class="older">
    <item dateTime="2009-02-01T11:59:00.000-05:00">carrots</item>
</div>
<div class="newer">
    <item dateTime="2009-02-01T11:59:00.000-05:00">eggplant</item>
</div>
<div class="older">
    <item dateTime="2009-02-01T11:59:00.000-05:00">grapes</item>
</div>
<div class="delete">
    <item dateTime="2009-04-01T11:59:00.000-05:00">oranges</item>
</div>
Elapsed Time (ms) 30

Generating an update list with unsorted inputs : Passed

Task If the sequences to be merged are not in sorted order, then they can be sorted before merging using the same sort criteria as wil be used in the merge.
XQuery
 
declare function local:time-merge($a, $b  as item()*  )  as item()* {
    if (empty($a) and empty($b))
    then ()
    else  if (empty ($b) or $a[1] lt $b[1])
    then  (<div class="add">{$a[1]}</div>, local:time-merge(subsequence($a, 2), $b))
    else  if (empty($a) or $a[1] gt $b[1])
    then  (<div class="delete">{$b[1]}</div>,local:time-merge($a, subsequence($b,2)))          
    else   (<div  class="{ if (xs:dateTime($a[1]/@dateTime) gt xs:dateTime($b[1]/@dateTime)) 
                                         then "newer" 
                                         else "older"}"> 
                      {$a[1]}
                </div>,
                 local:time-merge(subsequence($a,2), subsequence($b,2))
               )
   };

let $list1 :=
<list>
   <item dateTime="2009-02-01T11:59:00.000-05:00">cabbage</item>
   <item dateTime="2009-02-01T11:59:00.000-05:00">bananas</item>
   <item dateTime="2009-02-01T11:59:00.000-05:00">carrots</item>
   <item dateTime="2009-02-01T11:59:00.000-05:00">grapes</item>
   <item dateTime="2009-02-01T11:59:00.000-05:00">eggplant</item>
   <item dateTime="2009-06-01T11:59:00.000-05:00">apples</item>
  </list>
 
let $list2 :=
<list>
 <item dateTime="2009-03-01T11:59:00.000-05:00">carrots</item>
   <item dateTime="2009-02-01T11:58:00.000-05:00">eggplant</item>
   <item dateTime="2009-02-01T12:00:00.000-05:00">grapes</item>
   <item dateTime="2009-04-01T11:59:00.000-05:00">oranges</item>
   <item dateTime="2009-01-01T11:59:00.000-05:00">apples</item>
   <item dateTime="2009-02-01T11:59:00.000-05:00">bananas</item>
  </list>

return   local:time-merge(
              for $item in $list1/item order by $item return $item,
              for $item in $list2/item order by $item return $item
              ) 

   
Output
<div class="newer">
    <item dateTime="2009-06-01T11:59:00.000-05:00">apples</item>
</div>
<div class="older">
    <item dateTime="2009-02-01T11:59:00.000-05:00">bananas</item>
</div>
<div class="add">
    <item dateTime="2009-02-01T11:59:00.000-05:00">cabbage</item>
</div>
<div class="older">
    <item dateTime="2009-02-01T11:59:00.000-05:00">carrots</item>
</div>
<div class="newer">
    <item dateTime="2009-02-01T11:59:00.000-05:00">eggplant</item>
</div>
<div class="older">
    <item dateTime="2009-02-01T11:59:00.000-05:00">grapes</item>
</div>
<div class="delete">
    <item dateTime="2009-04-01T11:59:00.000-05:00">oranges</item>
</div>
Elapsed Time (ms) 32