如何在 XQuery 中找到两个节点的最低共同祖先?
How to find the lowest common ancestor of two nodes in XQuery?
假设输入 XML 是
<root>
<entry>
<title>Test</title>
<author>Me</author>
</entry>
</root>
我想找到 title
和 author
的最低共同祖先。
我在 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]
:第一个谓词考虑了具有 title
和 author
后代的元素。
[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.xq
。 intersect
要求在同一数据库中比较所有节点,每次对 文件 调用 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
假设输入 XML 是
<root>
<entry>
<title>Test</title>
<author>Me</author>
</entry>
</root>
我想找到 title
和 author
的最低共同祖先。
我在 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]
:第一个谓词考虑了具有title
和author
后代的元素。[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.xq
。 intersect
要求在同一数据库中比较所有节点,每次对 文件 调用 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