Groovy > 嵌套Map转为XML

7
我想在Groovy中将我的Map对象转换为XML。我查看了当前的示例,认为这应该更简单!
我找到的所有示例,要么使用MarkupBuilder手动指定字段,要么有一个实用程序方法迭代树。太可怕了!
我是否遗漏了什么?我可以轻松地将这些其他格式转换...
JsonOutput.prettyPrint(JsonOutput.toJson(map))    // json
(map as ConfigObject).writeTo(new StringWriter()) // groovy
new Yaml().dump(map, new StringWriter())          // yml

为什么我不能只是这样做?
XmlUtil.serialize(map)

(或者我如何将我的Map对象转换为Element / Node / GPathResult / Writable对象?)

Groovy示例代码

def myMap = [
    key1: 'value1',
    key2: 'value2',
    key3: [
        key1: 'value1',
        key2: 'value2',
        key3: [
            key1: 'value1',
            key2: 'value2',
        ]
    ]
]

首选输出

<root>
    <key1>value1</key1>
    <key2>value2</key2>
    <key3>
        <key1>value1</key1>
        <key2>value2</key2>
        <key3>
            <key1>value1</key1>
            <key2>value2</key2>
        </key3>
    </key3>
</root>
2个回答

14

您可以进行以下操作:

import groovy.xml.*

new StringWriter().with { sw ->
    new MarkupBuilder(sw).with {
        root { 
            myMap.collect { k, v ->
                "$k" { v instanceof Map ? v.collect(owner) : mkp.yield(v) }
            }
        }
    }
    println sw.toString()
}

输出:

<root>
  <key1>value1</key1>
  <key2>value2</key2>
  <key3>
    <key1>value1</key1>
    <key2>value2</key2>
    <key3>
      <key1>value1</key1>
      <key2>value2</key2>
    </key3>
  </key3>
</root>

据我所知,没有任何可以调用的魔法方法(可能是因为由于属性的存在,没有不知道所需输出结构的魔法映射 -> xml转换可以完成)。


注意:在收集器中添加if(v)或在yield内部添加v ?: "null"以避免元素具有空值时出现错误。 - キキジキ

0

其他可能的解决方案(这也适用于列表结构)...

结构

def myMap = [
    key1: 'value1',
    key2: 'value2',
    key3: [
        key1: 'value1',
        key2: 'value2',
        key3: [
            key1: 'value1',
            key2: 'value2',
        ],
        key4: [
            [ k1: true, k2: 123 ],
            [ k1: false, k2: 456 ]
        ]
    ]
]

代码


def parseNodes( StringBuilder b, node ){
    if ( node instanceof Map ){
        for ( def e in node ){
            def valuesAsList = e.value instanceof List ? e.value : [ e.value ]
            for ( def nodeElement : valuesAsList ){
                b.append( "<${e.key}>" )
                parseNodes(b, nodeElement)
                b.append( "</${e.key}>" )
            }
        }
    } else if ( node instanceof String ){
        def nodeText = groovy.xml.XmlUtil.escapeXml( node.toString() )
        b.append( nodeText )
    } else if ( node instanceof Number || node instanceof Boolean ){
        b.append( node.toString() )
    } else {
        throw new RuntimeException( "Xml parse failed, type " + node.getClass() + " value " + node )
    }
}

def objectToXml( object ){
    def b = new StringBuilder()
    b.append( "<root>" )
    parseNodes(b, object)
    b.append( "</root>" )
    return b.toString()
}

def xml = objectToXml( myMap )
println "Xml result -> " + xml

结果

<root>
    <key1>value1</key1>
    <key2>value2</key2>
    <key3>
        <key1>value1</key1>
        <key2>value2</key2>
        <key3>
            <key1>value1</key1>
            <key2>value2</key2>
        </key3>
        <key4>
            <k1>true</k1>
            <k2>123</k2>
        </key4>
        <key4>
            <k1>false</k1>
            <k2>456</k2>
        </key4>
    </key3>
</root>

...但是,我想建议使用像Jackson这样的库,这些库比手动创建XML更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接