2012-07-10 76 views
0

我對在Xquery中的遞歸函數的練習感到困擾。我只需要使用Xquery將一個平坦的XML樹轉換爲一個嵌套的XML樹。使用Xquery和遞歸函數將平坦的xml轉換爲嵌套的xml

平XML看起來是這樣的:

<?xml version="1.0"?> 
    <tree> 
     <node id="1" type="Folder"> 
     <child>2</child> 
     <child>3</child> 
     </node> 
     <node id="2" type="Folder"> 
     <child>4</child> 
     </node> 
     <node id="3" type="Folder"> 
     <child>5</child> 
     <child>6</child> 
     </node> 
     <node id="4" type="Item" /> 
     <node id="5" type="Folder"> 
     <child>7</child> 
     </node> 
     <node id="6" type="Item" /> 
     <node id="7" type="Item" /> 
    </tree> 

嵌套的XML需要看起來像這樣:

<?xml version="1.0"?> 
    <tree> 
     <node id="1" type="Folder" children="2 3"> 
     <node id="2" type="Folder"> 
      <node id="4" type="Item" /> 
     </node> 
     <node id="3" type="Folder"> 
      <node id="5" type="Folder" children="7"> 
      <node id="7" type="Item" /> 
      </node> 
      <node id="6" type="Item" /> 
     </node> 
     </node> 
    </tree> 

我試圖XQuery的這一點沒有遞歸函數,但沒有多少運氣。特別是空調對我來說似乎很陌生;新的嵌套XML的根元素應該是id =「1」的節點,因爲它不作爲任何其他元素的子元素存在。但是,如果我試圖將其指定爲條件,例如下面,似乎不可能選擇那個節點。

for $node in /Tree/node[@id != /Tree/node/child] 
    return 
    <node id="{data($node/@id)}" type="{data($node/@type)}"> 

      (: Lower level subqueries.... :) 

    </node> 

更新:我已經來了不少進一步,但現在我卡上有等於父節點的內容的ID節點的選擇[狀態],即for語句在遞歸函數中不會返回任何節點,這是意想不到的。

這是我的代碼至今:

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization"; 
    declare namespace local = "localhost"; 
    declare option output:method "xml"; 
    declare option output:omit-xml-declaration "no"; 
    declare option output:indent "yes"; 
    declare option output:doctype-system "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"; 

    declare function local:addSubNode($n) 
    { 
     for $subnode in doc("xml/flat-tree.xml")/tree/node[@id = $n] 
      let $subnid:=data($subnode/@id) 
      let $subtype:=data($subnode/@type) 
     return <node id="{$subnid}" type="{$subtype}"> 
       {local:addSubNode($subnid)} 
       </node> 
     }; 

    <tree> 

    { 
    for $node in doc("xml/flat-tree.xml")/tree/node[not(@id = /tree/node/child)] 
    let $nid:=data($node/@id) 

    return <node id="{$nid}" type="{data($node/@type)}"> 
     {for $child in $node 
     let $cid:=data($child) 
     return local:addSubNode($cid) 
     } 

      </node> 
    } 

    </tree> 

回答

0

好吧!最終,我將整個$ node或$ child元素提供給遞歸函數,而不僅僅是它的id屬性,現在它可以工作了!

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization"; 
    declare namespace local = "localhost"; 
    declare option output:method "xml"; 
    declare option output:omit-xml-declaration "no"; 
    declare option output:indent "yes"; 
    declare option output:doctype-system "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"; 

    (:lookupChildren function :) 
    declare function local:lookupChildren($p) 
    { 
    for $child in $p/child 
    return $child 
    }; 

    declare function local:addSubNode($n) 
    { 
    for $subnode in doc("xml/flat-tree.xml")/tree/node 
      let $subnid:=data($subnode/@id) 
      let $subtype:=data($subnode/@type) 
    where $subnode/@id = $n/child 
     return 
     <node id="{$subnid}" type="{$subtype}" children="{local:lookupChildren($subnode)}"> 
       {local:addSubNode($subnode)} 
       </node> 
    }; 

    <tree> 

    { 
    for $node in doc("xml/flat-tree.xml")/tree/node[not(@id = /tree/node/child)] 
    let $nid:=data($node/@id) 
    let $ntype:=data($node/@type) 

    return <node id="{$nid}" type="{$ntype}" children="{local:lookupChildren($node)}"> 
      {local:addSubNode($node)} 

      </node> 
    } 

    </tree> 
0

只是一個片面的答案 - =!=可以針對序列比較原子值,但它可以作爲一個邏輯或反對每學期。那就是「a = b」的意思是「在b中有沒有等於a的值」,「a!= b」的意思是「在b中有不等於a的值」,這不是你正在尋找的東西。你想要「在b中沒有任何值等於」,「不是(a = b)」。

for $node in $d/node[not(@id = $d/node/child)] return 
<node id="{$node/@id}" type="{$node/@type}"> 
    (: etc. :) 
</node> 
+0

感謝您的回覆,我會給它一個新的限制! – 2012-07-11 07:40:20

+0

我想我差不多在那裏,但不能在遞歸函數中使[]選擇工作。任何想法可能是我的最新查詢錯誤?往上看。 – 2012-07-11 21:30:24

+0

在遞歸函數中甚至可以使用$ cid變量作爲$ n嗎? – 2012-07-12 07:13:34