-2

Please consider this naive example:

    let $Best := <root>
           <p name='p1'>
              <s name='s1'>
                 <line nr='1' ci='0'/>
                 <line nr='2' ci='10'/>
               </s>
               <s name='s2'>
                  <line nr='5' ci='2'/>
                  <line nr='6' ci='3'/>
                </s>
             </p>
           <p name='p2'>
               <s name='s1'>
                  <line nr='34' ci='0'/>
                  <line nr='35' ci='1'/>
                </s>
               <s name='s2'>
                   <line nr='37' ci='2'/>
                   <line nr='38' ci='3'/>
                </s>
            </p>
         <root>

    let $Least :=
           <root>
            <p name='p1'>
               <s name='s1'>
                 <line nr='1' ci='15'/>
                 <line nr='2' ci='1'/>
               </s>
                <s name='s2'>
                   <line nr='5' ci='2'/>
                   <line nr='6' ci='5'/>
                </s>
              </p>
            <p name='p2'>
               <s name='s1'>
                    <line nr='34' ci='0'/>
                   <line nr='35' ci='0'/>
                </s>
               <s name='s2'>
                 <line nr='37' ci='1'/>
                 <line nr='38' ci='7'/>
                </s>
             </p>
           <root>

These nodes have the same tag structure and the same attribute values except for the value of attribute "ci". I need a xquery function that builds a new node $Result from $Best replacing every its node "line" that has attribute "ci" less than the value of same attribute "ci" of the corresponding node "line" of $Least :

   $Result := <root>
              <p name='p1'>
                  <s name='s1'>
                    <line nr='1' ci='15'/>
                    <line nr='2' ci='10'/>
                  </s>
                  <s name='s2'>
                     <line nr='5' ci='2'/>
                     <line nr='6' ci='5'/>
                   </s>
                 </p>
                <p name='p2'>
                   <s name='s1'>
                     <line nr='34' ci='0'/>
                     <line nr='35' ci='1'/>
                    </s>
                   <s name='s2'>
                        <line nr='37' ci='2'/>
                        <line nr='38' ci='7'/>
                    </s>
                 </p>
              <root> 

Thank you in advance for your help.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • 1
    Welcome to SO. Please read the [FAQ] and [Ask] for tips on writing good questions. You are expected to put some effort into solving the problem yourself instead of just presenting a problem and expecting someone else to solve it for you. – Jim Garrison Sep 02 '14 at 22:51

1 Answers1

0

Use recursion, and walk the trees in parallel, matching on whichever identifier you have available (@name, @nr). When you reach the leaf node <line>, sort the @ci values and take the largest.

declare function local:diff-cis(
  $best as node(),
  $least as node()
) as node()?
{
  typeswitch($best)
    case element(root) | element(p) | element(s) return 
      element { node-name($best) } {
        $best/@name,
        for $n in $best/*
        return local:sub-cis($n, 
          $least/*[@name=$n/@name or @nr=$n/@nr])  
      }
    case element(line) return
      element line {
        $best/@nr, 
        attribute ci { 
          (for $ci in ($least/@ci, $best/@ci)
          order by $ci descending
          return $ci)[1]
        }
      }
    default return ()
};

local:diff-cis($Best, $Least)
wst
  • 11,681
  • 1
  • 24
  • 39
  • @user3664323 If this answer is sufficient, please accept it by clicking the little checkbox to the left. – wst Sep 03 '14 at 13:38