根据具有相同标记结构的两个xml文件的差异创建节点

时间:2014-09-02 22:47:49

标签: xml xquery difference xmlnode

请考虑这个天真的例子:

    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>

这些节点具有相同的标签结构和相同的属性值,除了属性&#34; ci&#34;的值。 我需要一个xquery函数来构建一个新的节点$ Result,从$ Best替换每个节点&#34; line&#34;有属性&#34; ci&#34;小于相同属性的值&#34; ci&#34;对应节点&#34; line&#34;至少:

   $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> 

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

使用递归,并行处理树,匹配您可用的任何标识符(@ name,@ nr)。当您到达叶节点<line>时,对@ci值进行排序并取最大值。

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)