具有递归定义的 XPath

XPath with recursive definitions

我有这样的 DTD:

     <!ELEMENT Root (Thread*) >
     <!ELEMENT Thread(ThreadId, Message) >
    <!ELEMENT Replies(message+) >
     <!ELEMENT message(timestamp, sender, recipient, subject, text, Replies?)>

所以一个线程会有一个消息,这个消息可以有一个节点'replies',然后这个节点可以包含消息等等,直到结构的底部。

现在我要做的是先检索消息最多的线程的 ID,然后检索嵌套回复链最长的线程的 ID。

这感觉像是一个递归问题,但我无法在 XPath 中处理它。到目前为止,我尝试过这样的事情:

      For $thread in //thread
      Count(descendant-or-self::$thread/message) 

对于每个线程,我尝试计算子消息节点的数量,但此解决方案计算线程的所有子节点的数量,因此包括回复节点。

我对这类问题感到迷茫,因为我不知道在这些问题中该做什么 'recursive situations'。

假设您可以使用 XPath 3.0,例如

let $max := max(/Root/Thread/count(.//Message))
return /Root/Thread[count(.//Message) eq $max]/ThreadId

查找消息最多的线程的 ID,我认为

let $max := max(/Root/Thread/Message//Replies[not(Message/Replies)]/count(ancestor::Replies))
return /Root/Thread[Message//Replies[not(Message/Replies)]/count(ancestor::Replies) = $max]/ThreadId

查找具有最长嵌套回复链的线程的 ID。

对于 XPath 2.0,您没有 let 表达式,因此您必须将示例中绑定的代码内联到引用变量的位置。

在 XPath 3.1 中,您有一个 sort 函数 (https://www.w3.org/TR/xpath-functions-31/#func-sort),因此无需计算最大值并选择具有最大值的项目,您可以排序并取最后一个,例如

sort(/Root/Thread, (), function($t) { max($t/Message//Replies[not(Message/Replies)]/count(ancestor::Replies)) })[last()]/ThreadId

对于第二个更复杂的查询或

sort(/Root/Thread, (), function($t) { count($t//Message) })[last()]/ThreadId

第一个。