我有这样的DTD:
<!ELEMENT Root (Thread*) >
<!ELEMENT Thread(ThreadId, Message) >
<!ELEMENT Replies(message+) >
<!ELEMENT message(timestamp, sender, recipient, subject, text, Replies?)>
因此,一个线程将有一条消息,并且此消息可以有一个节点&#39;回复&#39;,然后该节点可以包含消息等,直到结构的底部。
现在我想要做的是首先检索具有最多消息的线程的ID,然后检索具有最长嵌套回复链的线程的ID。
这感觉就像一个递归问题,但我无法在XPath中接近它。到目前为止,我尝试过这样的事情:
For $thread in //thread
Count(descendant-or-self::$thread/message)
对于每个线程,我尝试计算子消息节点的数量,但此解决方案计算线程的所有子节点的数量,因此包括回复节点。
我对这类问题感到迷茫,因为我无法弄清楚在这些“递归”情况下应该做些什么。
答案 0 :(得分:0)
假设XPath 3.0可以使用例如
let $max := max(/Root/Thread/count(.//Message))
return /Root/Thread[count(.//Message) eq $max]/ThreadId
找到包含大多数消息的线程的id(s),我认为
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
第一个。