2016-09-07 4 views
1

とフラットなXMLからツリー形式のXMLを作成する:私は次の形式でいくつかのXMLを持っているXqueryの

<data> 
    <row> 
     <id>1</id> 
     <parent_id/> 
    </row> 
    <row> 
     <id>2</id> 
     <parent_id>1</parent_id> 
    </row> 
    <row> 
     <id>3</id> 
     <parent_id>1</parent_id> 
    </row> 
    <row> 
     <id>4</id> 
     <parent_id>5</parent_id> 
    </row> 
    <row> 
     <id>5</id> 
     <parent_id/> 
    </row> 
    <row> 
     <id>6</id> 
     <parent_id>2</parent_id> 
    </row> 
    <row> 
     <id>7</id> 
     <parent_id>4</parent_id> 
    </row> 
</data> 

私はこのような何かにそれを回すためにしようとしている:私は希望

<data> 
    <row> 
    <id>1</id> 
    <children> 
     <row> 
     <id>2</id> 
     <parent_id>1</parent_id> 
     <children> 
      <id>6</id> 
      <parent_id>2</parent_id> 
      <children/> 
     </children> 
     </row> 
     <row> 
     <id>3</id> 
     <parent_id>1</parent_id> 
     <children/> 
     </row> 
    </children> 
    <parent_id/> 
    </row> 
    <row> 
    <id>5</id> 
    <parent_id/> 
    <children> 
     <row>   
      <id>4</id> 
      <parent_id>5</parent_id> 
      <children> 
      <row> 
       <id>7</id> 
       <parent_id>4</parent_id> 
       <children/> 
      </row> 
      </children> 
     </row> 
    </children> 
    </row> 
</data> 

複数のルートノードがある場合(親なし)、このフラットデータを複数のツリーに分割することができます。次のすべての子は、親の要素<children>に再帰的に追加されます。

私はこの種の再帰に近づくためのいくつかの助けを使うことができるように、Xqueryの新機能です。私はルートとセカンドレベルを作り出すことができましたが、どのようにこれを再現し、すべての子レベルが複数のパスを持つことができるかを考慮する必要がありますか?私はボーナスとして、これとは逆のやり方に興味を持っています:リーフから始まり、そこから親要素内に同様の構造を追加することに興味があります。

ルート要素とその子を返します。私の現在のコード:

declare function local:root() { 
    let $root := doc("source.xml")/Result/Rows/Row[parent_object_id = ''] 
    return $root 
}; 

declare function local:recurse($input) { let 
    $children := doc("source.xml")/Result/Rows/Row[parent_object_id = $input/object_id] 
    return $children 
}; 

<result> 
    <object_id>{local:root()/object_id/text()}</object_id> 
    <parent_object_id>{local:root()/parent_object_id/text()} </parent_object_id> 
    <children>{local:recurse(local:root())}</children> 
</result> 
+0

こんにちは。どのルールを適用していますか?ビジネスロジックとコードを含めてください。 –

+0

これまで私が思いついたことを加えました。 –

答えて

0

あなたはそれを行うには、再帰関数を使用することができます。

declare function local:nest-children($data, $id) { 
    <row>{ 
    $id, 
    <children>{ 
     for $child in $data/row[parent_id = $id] 
     return local:nest-children($data, $child/id) 
    }</children> 
    }</row> 
}; 

<data>{ 
    for $outer in $data/row[empty(parent_id/text())] 
    return local:nest-children($data, $outer/id) 
}</data> 

これは、次の結果を返します。

<data> 
    <row> 
    <id>1</id> 
    <children> 
     <row> 
     <id>2</id> 
     <children> 
      <row> 
      <id>6</id> 
      <children/> 
      </row> 
     </children> 
     </row> 
     <row> 
     <id>3</id> 
     <children/> 
     </row> 
    </children> 
    </row> 
    <row> 
    <id>5</id> 
    <children> 
     <row> 
     <id>4</id> 
     <children> 
      <row> 
      <id>7</id> 
      <children/> 
      </row> 
     </children> 
     </row> 
    </children> 
    </row> 
</data> 
+0

まさに私が探していたもの、ありがとうございました。 –

関連する問題