[xquery-talk] node comparison based on qualified name

Ghislain Fourny gfourny at inf.ethz.ch
Thu Jun 23 05:16:51 PDT 2011


Hi,

Would the following function help (you would need to adapt the output of course)?

I made the following assumptions:
- the order is not important
- the output should contain a list of what was "inserted", as well as a list of what was "deleted"
- QNames might occur multiple times in each sequence (to be general)
- if QNames occur multiple times and their count is different, then it does not matter which of the nodes with this QName are taken for the delta (the function below takes the last abs($count-right - $count-left) ones).

Does it make sense?

Kind regards,
Ghislain


declare function local:compare($seq1, $seq2)
{
  let $qnames1 := distinct-values($seq1/name())
  let $qnames2 := distinct-values($seq2/name())
  return (
    <inserted>{
      for $qname-in-common in $qnames1[. = $qnames2]
      let $count-left := count($seq1[name() = $qname-in-common])
      let $count-right := count($seq2[name() = $qname-in-common])
      where $count-left lt $count-right
      return $seq2[name() = $qname-in-common][position() gt last() - ($count-right - $count-left)],
      
      for $qname-right-only in $qnames2[not(. = $qnames1)]
      return $seq2[name() = $qname-right-only]
    }</inserted>,
    <deleted>{
      for $qname-in-common in $qnames1[. = $qnames2]
      let $count-left := count($seq1[name() = $qname-in-common])
      let $count-right := count($seq2[name() = $qname-in-common])
      where $count-right lt $count-left
      return $seq1[name() = $qname-in-common][position() gt last() - ($count-left - $count-right)],
      
      for $qname-left-only in $qnames1[not(. = $qnames2)]
      return $seq1[name() = $qname-left-only]
    }</deleted>
  )
};


This returns for your $seq1/* and $seq2/*:
<inserted/><deleted/>
(no difference)

and for your $seq1/* and $seq3/*:
<inserted/>
<deleted>
  <alName>aaa</alName>
</deleted>

With a more complicated example:

let $seq4 :=
    <author>
      <node1>aaa</node1>
      <node2>aaa</node2>
      <node2>aaa</node2>
      <node3>aaa</node3>
    </author>
let $seq5 :=
    <author>
      <node1>bbb</node1>
      <node1>bbb</node1>
      <node2>bbb</node2>
      <node4>bbb</node4>
    </author>
return local:compare($seq4/*, $seq5/*)

returns

<inserted>
  <node1>bbb</node1>
  <node4>bbb</node4>
</inserted>
<deleted>
  <node2>aaa</node2>
  <node3>aaa</node3>
</deleted>





More information about the talk mailing list