使用Xquery

时间:2016-09-07 13:46:35

标签: xml xquery

我有以下格式的XML:

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

如果有多个根节点(没有父节点),我想将只有父ID的平面数据排序到多个树中。以下所有子项将以递归方式添加到其父级的<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>

1 个答案:

答案 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>