Groovy中的Xml树构建器

时间:2013-02-28 01:55:40

标签: groovy

给定给定节点的id和路径的映射,我构建了一个xml树:

def trees = [:]
trees.put(1,"TEST/folder1")
trees.put(2,"TEST/folder2")
trees.put(3,"TEST/folder1/folder1.1")
trees.put(4,"TEST/folder2/folder2.1/folder2.1.2")
trees.put(5,"TEST/folder1/folder1.2") 
trees.put(6,"TEST/folder1/folder1.2/folder1.2.1/")                        
trees.put(7,"TEST/folder1/folder1.2/folder1.2.2/")
trees.put(8,"TEST/folder1/folder1.2/folder1.2.2/1.2.2.1")       


sw = new StringWriter()

def rslt = { [:].withDefault{ owner.call() } }().with { t ->
  trees.each { k, v ->
      v.tokenize( '/' ).inject( t ) { tr, i -> tr[ i ] }
  }
  return t
}

new groovy.xml.MarkupBuilder(sw).with {
            visitor = { k, v -> "$k" { v instanceof Map ? v.collect(visitor) : mkp.yield(v) } }
            ROOT { rslt.collect visitor }
        }
println sw.toString()       

最后得到这个输出:

 <TEST>
    <folder1>
      <folder1.1 />
      <folder1.2>
        <folder1.2.1 />
        <folder1.2.2>
          <1.2.2.1 />
        </folder1.2.2>
      </folder1.2>
    </folder1>
    <folder2>
      <folder2.1>
        <folder2.1.2 />
      </folder2.1>
    </folder2>
  </TEST>
</ROOT>

是否有一种常规的方法来添加属性id,name,parent depth,url,herited from initial tree map values?

格式良好的xml doc示例:

<folder2 name="folder2" id="2" parent="TEST" depth="1" url="TEST/folder2">
      <folder2.1.1 name="folder2.1.1" id="2" parent="TEST" depth="2" url="TEST/folder2">
           <folder2.1.1.1 name="folder2.1.1.1" id="3" parent="TEST" depth="3" url="TEST/folder2"/>
       </folder2.1.1>
</folder2>

有任何想法或建议吗?

干杯

1 个答案:

答案 0 :(得分:0)

我将开始假设您的模型并创建一些模拟数据:

class Dir {
  String name, url, id
  Dir parent
  List<Dir> children

  String toString() { "Dir(name:$name, url:$url, parent:$parent)" }
}

dir1 = new Dir( name: "folder1", url: "TEST/folder1", id: "1" )
dir2 = new Dir( name: "folder2", url: "TEST/folder2", id: "2" )
dir11 = new Dir( name: "folder1.1", url: "TEST/folder1/folder1.1", id: "11", parent: dir1 )
dir12 = new Dir( name: "folder1.2", url: "TEST/folder1/folder1.2", id: "12", parent: dir1 )
dir121 = new Dir( name: "folder1.2.1", url: "TEST/folder1/folder1.2/folder1.2.1", id: "121", parent: dir12 )
dir212 = new Dir( name: "folder2.1.2", url:"TEST/folder2/folder2.1/folder2.1.2", id: "212", parent: dir2 )

dir1.children = [dir11, dir12]
dir12.children = [dir121]
dir2.children = [dir212]

dirs = [dir1, dir2]

现在您只需使用markupbuilder或streamingmarkupbuilder构建xml结构,使用gstrings创建动态标记:

sw = new StringWriter()

def depthCalculator // used to calculate the depth of the folder object
depthCalculator = { Dir dir, Integer count = 1 -> 
  if (dir.parent) depthCalculator dir.parent, count++
  count 
}

new groovy.xml.MarkupBuilder(sw).with {

  setDoubleQuotes true

  /*
   * This closure creates the tag using a gstring for the tag name. 
   * It recursively iterates through every children of the Dir parent object.
   */
  def collector 
  collector = { Dir dir -> 
    def depth = depthCalculator dir
    "${dir.name}" (
          name: dir.name, 
          id: dir.id, 
          url: dir.url, 
          parent: (dir.parent?.name ?: ""), 
          depth: depth) { 
      dir.children.each collector
    }
  }

  dirs.each collector
}

println sw.toString()  

这是生成的XML:

<folder1 name="folder1" id="1" url="TEST/folder1" parent="" depth="1">
  <folder1.1 name="folder1.1" id="11" url="TEST/folder1/folder1.1" parent="folder1" depth="2" />
  <folder1.2 name="folder1.2" id="12" url="TEST/folder1/folder1.2" parent="folder1" depth="2">
    <folder1.2.1 name="folder1.2.1" id="121" url="TEST/folder1/folder1.2/folder1.2.1" parent="folder1.2" depth="2" />
  </folder1.2>
</folder1>
<folder2 name="folder2" id="2" url="TEST/folder2" parent="" depth="1">
  <folder2.1.2 name="folder2.1.2" id="212" url="TEST/folder2/folder2.1/folder2.1.2" parent="folder2" depth="2" />
</folder2>