如何在 XQuery 中找到两个节点的最低共同祖先?

How to find the lowest common ancestor of two nodes in XQuery?

假设输入 XML 是

<root>
<entry>
    <title>Test</title>
    <author>Me</author>
  </entry>
</root>

我想找到 titleauthor 的最低共同祖先。 我在 BaseX 中尝试了以下代码:

 let $p := doc('t.xq')//title, 
 $q := doc('t.xq')//author, 
 $cla := ($p/ancestor-or-self::node() intersect $q/ancestor-or-self::node()) 
 return 
    $cla

但它returns什么都没有(空白输出)。

这是一种可能的方式:

let $db := doc('t.xq'), 
$q := $db//*[.//title and .//author][not(.//*[.//title and .//author])]
return 
  $q

简要说明:

  • [.//title and .//author] :第一个谓词考虑了具有 titleauthor 后代的元素。

  • [not(.//*[.//title and .//author])] :然后第二个谓词将相反的标准应用于后代元素,这意味着总体上我们只接受符合第一个谓词标准的最内层元素。

输出:

<entry>
  <title>Test</title>
  <author>Me</author>
</entry>

你的代码对我来说完全没问题,除了 returning all 共同祖先。

最后的共同祖先

由于它们是按文档顺序 return 编辑的,并且最后一个共同祖先也必须是最后一个节点,因此只需使用 [last()] 谓词进行扩展。

declare context item := document {
  <root>
    <entry>
      <title>Test</title>
      <author>Me</author>
    </entry>
  </root>
};

let $p := //title, 
    $q := //author, 
    $cla := ($p/ancestor-or-self::node() intersect $q/ancestor-or-self::node())[last()]
return 
    $cla

文件和数据库

如果您发布的查询没有 return 任何内容,您可能正在处理文件 t.xqintersect 要求在同一数据库中比较所有节点,每次对 文件 调用 doc(...) 都会创建一个新的内存数据库。用内容在 BaseX 中创建一个数据库,或者做类似

的事情
declare variable $doc := doc('t.xq');

并用 $doc 替换后续 doc(...) 调用(现在引用为文件创建的 单个 内存数据库)。

我把变量$p$q前面的doc('t.xq')改成了变量$db,如下。现在它起作用了(另外,我使用 last() 来拥有最后一个(最低的)共同祖先)。

let 
$db := doc('t.xq'),
$p := $db//title, 
$q := $db//author, 
$cla := ($p/ancestor-or-self::node() intersect $q/ancestor-or-self::node())[last()] 
return $cla