XQuery:按特定顺序查找具有后代的节点

XQuery: look for node with descendants in a certain order

我有一个 XML 文件,代表一本书中所有句子的语法树:

<book>
    <sentence>
        <w class="pronoun" role="subject">
            I
        </w>
        <wg type="verb phrase">
            <w class="verb" role="verb">
                like
            </w>
            <wg type="noun phrase" role="object">
                <w class="adj">
                    green
                </w>
                <w class="noun">
                    eggs
                </w>
            </wg>
        </wg>
    </sentence>
    <sentence>
        ...
    </sentence>
    ...
</book>

这个例子是假的,但关键是实际的单词(<w> 元素)是根据句法关系以不可预测的方式嵌套的。

我想要做的是找到 <sentence> 个节点,其中 <w> 个子节点以 特定顺序 匹配特定条件。例如,我可能正在寻找带有 w[@class='pronoun'] 后代后跟 w[@class='verb'] 后代的句子。

很容易找到只包含两个后代的句子,而不用关心顺序:

//sentence[descendant::w[criteria1] and descendant::w[criteria2]]

我确实设法弄清楚了这个查询做我想做的事情,它寻找一个 <w> 与以下 <w> 匹配标准与最接近的 <sentence> 祖先:

for $sentence in //sentence
where $sentence[descendant::w[criteria1 and 
    following::w[(ancestor::sentence[1] = $sentence) and criteria2]]]
return ...

...但不幸的是它很慢,我不确定为什么。

有没有一种不慢的方法来搜索包含按特定顺序匹配条件的后代的节点?我将 XQuery 3.1 与 BaseX 一起使用。如果我找不到使用 XQuery 执行此操作的合理方法,则计划 B 是使用 Python.

进行 post 处理

following 轴确实很昂贵,因为它跨越文档的所有后续节点,这些节点既没有后代也没有祖先。

节点比较运算符(<<>>is)可能会对您有所帮助。在下面的代码示例中,检查是否至少有一个动词后跟一个名词:

for $sentence in //sentence
let $words1 := $sentence//w[@class = 'verb']
let $words2 := $sentence//w[@class = 'noun']
where some $w1 in $words1 satisfies 
      some $w2 in $words2 satisfies $w1 << $w2
return $sentence