2017-07-18 76 views
1

我有這樣的DTD:的XPath遞歸定義

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

所以線程將有一個消息,這個消息可以有一個節點「回覆」,那麼這個節點可以包含消息,並依此類推,直到結構的底部。

現在我想要做的是首先檢索具有最多消息的線程的ID,然後檢索具有最長嵌套應答鏈的線程的ID。

這感覺就像一個遞歸問題,但我無法在XPath中處理它。到目前爲止,我嘗試過這樣的事情:

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

對於每個線程我試着算兒童信息節點的數量,但這種方法計算的線程的所有子節點的數量,因此包括回覆節點。

我對這種問題感到迷茫,因爲我無法弄清楚在這些'遞歸情況下'要做什麼。

+0

那麼您可以訪問哪個版本的XPath? 2.0,3.0,3.1? –

回答

0

假設XPath 3.0可以使用例如

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

找到線程(S)與大多數郵件的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(S)最長鏈嵌套答覆。

對於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 

爲第一個。

+0

非常感謝您的答案,我正在使用XPath 3.0!他們工作! – Pagli

+0

你好,我需要最後一件事!要找到具有最長嵌套回覆鏈的線程,它可以簡單地找到線程中回覆計數的最大值,如下所示:'count(/ Root/Thread // Replies)' 這樣我們也可以計算第一個答覆,但我想這不重要,因爲我們將有嵌套答覆的數量加上第一個答覆,爲每個線程。 – Pagli

+0

問題是'count(/ Root/Thread // Replies)'表達式在深度和樹的寬度上統計了所有的'Replies'後代,所以我不會將它看作是確定最大嵌套。 –