# [xquery-talk] distance between elements and hierarchical order

Sergio Andreozzi sergio.andreozzi at cnaf.infn.it
Fri Dec 9 13:25:50 PST 2005

```I worked also on the following issue:

3. measure the distance between two elements as regards the document
structure

the solution that I've defined so far works in the following way: given
two elements, for each of them I build a sequences with their QName plus
the QNames of their ancestors; I compare the two sequences memberwise
and I count the common QNames starting from the root; finally, I add the
number of QNames in the first sequence to the number of QNames in the
second sequence, I substract twice the common elements and I add 1 for
the closest common ancestor:

let \$x-names :=
(doc("test.xml")/S/A/B/F)[2]/ancestor-or-self::element()/name(),
\$y-names :=
(doc("test.xml")/S/A/B/C/G/H)[3]/ancestor-or-self::element()/name()

return count(\$x-names) + count(\$y-names) + 1 - 2*count(
for \$x-name at \$x-pos in \$x-names
where \$x-name eq \$y-names[\$x-pos]
return 1)

as regards the example in
http://xquery.com/pipermail/talk/2005-December/000944.html, this measure
always provides 5.

This is the best refinement I managed to design so far in order to
perform this measure.

Regards, Sergio

Sergio Andreozzi wrote:
> David Carlisle wrote:
>
>> In the original problem I don't think you need to explictly iterate over
>> the ancestor lists then use count and min, you just walk up the
>> ancestors of x which are not ancestors of y , then up one level to the
>> nearest common ancestor then down the ancestors of y that are not
>> ancestors of x so the distance is
>>
>> count(\$x-ancestors)+count(\$y-ancestors)+1-2*count(\$x-ancestors
>> intersect \$y-ancestors)
>>
>> where x-ancestors is as in the posted code the ancestor-or-self:: axis
>> from \$x
>
>
>
> the final solution for prob. no.2 should be this one then:
>
> let \$x := ...
>     \$y := ...
>
> let \$x-ancestors := \$x/ancestor-or-self::element(),
>     \$y-ancestors := \$y/ancestor-or-self::element()
>
> return count(\$x-ancestors)+count(\$y-ancestors)+1-2*count(\$x-ancestors
> intersect \$y-ancestors)
>
> ex.1
>
> let \$x := (doc("test.xml")/S/A/B/F)[1],
>     \$y := (doc("test.xml")/S/A/B/C/G/H)[3]
>
> result is 7
>
> ex.2
>
> let \$x := (doc("test.xml")/S/A/B/F)[2],
>     \$y := (doc("test.xml")/S/A/B/C/G/H)[3]
>
> result is 5
>
> where test.xml is:
>
> <S>
>     <A>
>         <B>
>             <F>4</F>
>             <C>
>                 <D>3</D>
>                 <E>5</E>
>                 <G>
>                     <H>3</H>
>                 </G>
>                 <G>
>                     <H>2</H>
>                 </G>
>             </C>
>         </B>
>         <B>
>         <F>2</F>
>         <C>
>             <G>
>                  <H>2</H>
>             </G>
>         </C>
>         </B>
>     </A>
> </S>
>
>
>
> thank you very much for your help.
>
>     Kind regards, Sergio
> _______________________________________________
> talk at xquery.com
> http://xquery.com/mailman/listinfo/talk

--
Sergio Andreozzi
INFN-CNAF,                        Tel: +39 051 609 2860
Viale Berti Pichat, 6/2           Fax: +39 051 609 2746
40126 Bologna (Italy)             Web: http://www.cnaf.infn.it/~sergio
```