3

Groovy MarkupBuilderを使用して Map を XML に変換しています。このマップには、単純なキーと値のペア、他のマップ、またはマップのリストを含めることができます。ここのコードからピギーバックしています。

import groovy.xml.MarkupBuilder

def map = [
    key1:'value1',
    key2:'value2',
    nestedMap : [
        key1:'bar1',
        key2:'bar2'
    ],
    select : [
        [option:'foo1'],
        [option:'foo2']
    ]
]

Closure renderMap( Map map ){
    return { 
        for ( entry in map ){
            switch( entry.value.getClass() ){
                case Map :
                    "${entry.key}" renderMap( entry.value )
                break
                case List:
                    entry.value.collect { listEntry ->
                        "${entry.key}" renderMap( listEntry )
                    }
                    break
                default :
                     "${entry.key}"( "${entry.value}" )
                break
            }
        }
    }
}

StringWriter writer = new StringWriter()
new MarkupBuilder(writer).root renderMap(map)

println writer.toString()

私が心配しているこの部分は、次のように出力されます。

  <select>
    <option>foo1</option>
  </select>
  <select>
    <option>foo2</option>
  </select>

ただし、次のように、選択を取得して両方のオプションをカプセル化する方法があるかどうか疑問に思っています。

<select>
    <option>foo1</option>
     <option>foo2</option>
  </select>

キーの配置をいじってみましたが、だめでした。私はこれについてすべて間違っているのでしょうか、それともビルダーを使用すべきではありませんか?

4

2 に答える 2

6

私はこれがあなたが望むことをするだろうと思います。最初の2つのオーバーロードは、マップまたはコレクションを取得し、マップまたはコレクションのコンテンツをビルダーに追加するために、囲んでいる要素のビルダーメソッドに渡すことができる構成されたクロージャーを返します。

3つ目はフォールバックであり、引数を返すだけなので、ビルダーメソッドに渡すことができます。これは文字列を処理しますが、必要に応じてクロージャーを渡すこともできます。optionその例として、提供したマップの2番目の要素を置き換えました。

ComposedClosureGroovy 1.8で追加されたため、これは以前のバージョンでは機能しません。

import groovy.xml.MarkupBuilder

Closure buildxml(final Map map)
{
    final compose = { f, tag, content -> f >> { "$tag"(buildxml(content)) } }
    return map.inject(Closure.IDENTITY, compose)
}

Closure buildxml(final Collection col)
{
    final compose = { f, content -> f >> buildxml(content) }
    return col.inject(Closure.IDENTITY, compose)
}

def buildxml(final content)
{
    return content
}

def map = [
    key1:'value1',
    key2:'value2',
    nestedMap : [
        key1:'bar1',
        key2:'bar2'
    ],
    select : [
        [option:'foo1'],
        { option('foo2') },
    ],
]

final writer  = new StringWriter()
final builder = new MarkupBuilder(writer)

builder.root buildxml(map)

assert writer as String == '''\
<root>
  <key1>value1</key1>
  <key2>value2</key2>
  <nestedMap>
    <key1>bar1</key1>
    <key2>bar2</key2>
  </nestedMap>
  <select>
    <option>foo1</option>
    <option>foo2</option>
  </select>
</root>'''.stripIndent()
于 2012-10-27T07:22:25.440 に答える
1

する

case List:
    "${entry.key}" entry.value.collect {
        renderMap it
    }
    break

あなたをどこにでも連れて行きますか?とはいえ、コンピューターで atm をチェックするわけではありませんが、それは正しいと思いますか?

于 2012-10-26T23:02:04.770 に答える