给定一个不确定深度的Groovy Map,每个级别都具有"属性"和"元素"关键,我正在寻找一种从这张地图递归构建XML的方法:
Map map = [
root: [
elements : [
node1: [
elements : [
key1Node1: "elementValue1Node1",
key2Node1: "elementValue2Node2",
],
attributes: [
attribute1Node1: "attributeValue1node1",
attribute2Node1: "attributeValue2node1",
attribute3Node1: "attributeValue3node1"
]
],
node2: [
elements : [
key1Node2: "elementValue1Node2",
key2Node2: "elementValue2Node2",
],
attributes: [
attribute1Node2: "attributeValue1node2",
attribute2Node2: "attributeValue2node2",
attribute3Node2: "attributeValue3node2"
]
]
],
attributes: [
rootAttribute: "iniciarSesion"
]
]
]
生成的XML应如下所示:
<root rootAttribute="rootValue">
<node1 attribute1Node1="attributeValue1node1" attribute2Node1="attributeValue2node1" attribute3Node1="attributeValue3node1">
<key1Node1>elementValue1Node1</key1Node1>
<key2Node1>elementValue2Node2</key2Node1>
</node1>
<node2 attribute1Node1="attributeValue1node2" attribute2Node1="attributeValue2node2" attribute3Node1="attributeValue3node2">
<key1Node2>elementValue1Node2"</key1Node2>
<key2Node2>elementValue2Node2</key2Node2>
</node2>
</root>
到目前为止,我已经尝试过使用一种方法,该方法可以遍历对象并在每个回合中添加必要的节点。 Groovy documentation for markupBuilder表明createNode方法可以获取属性的映射和值的对象。所以我尝试了以下方法:
static def makeXmlBody(map) {
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
map.each {
k, v ->
if (v.getClass() == LinkedHashMap) {
xml.createNode(k, v.attributes, makeXmlBody(v.elements))
println(writer)
} else {
xml.createNode(k, v)
println(writer)
}
}
}
我们的想法是,如果价值是地图,那么它必须具有&#34;元素&#34;和&#34;属性&#34;在里面。因此,我们可以将字段键作为第一个参数,即节点&#34;属性&#34; map作为第二个,并且递归调用与第三个函数相同的函数,以便构建每个级别。
问题是,似乎每个级别都保持下面的每个级别不变,所以在输出中(参见代码中的两个printlns),我看到每个级别都在正确地完成,但是最终的结果是不是是有用的。
<key1Node1>elementValue1Node1
<key1Node1>elementValue1Node1
<key2Node1>elementValue2Node2
<node1 attribute1Node1='attributeValue1node1' attribute2Node1='attributeValue2node1' attribute3Node1='attributeValue3node1'>{key1Node1=elementValue1Node1, key2Node1=elementValue2Node2}
<key1Node2>elementValue1Node2
<key1Node2>elementValue1Node2
<key2Node2>elementValue2Node2
<node1 attribute1Node1='attributeValue1node1' attribute2Node1='attributeValue2node1' attribute3Node1='attributeValue3node1'>{key1Node1=elementValue1Node1, key2Node1=elementValue2Node2}
<node2 attribute1Node2='attributeValue1node2' attribute2Node2='attributeValue2node2' attribute3Node2='attributeValue3node2'>{key1Node2=elementValue1Node2, key2Node2=elementValue2Node2}
<root rootAttribute='iniciarSesion'>{node1={elements={key1Node1=elementValue1Node1, key2Node1=elementValue2Node2}, attributes={attribute1Node1=attributeValue1node1, attribute2Node1=attributeValue2node1, attribute3Node1=attributeValue3node1}}, node2={elements={key1Node2=elementValue1Node2, key2Node2=elementValue2Node2}, attributes={attribute1Node2=attributeValue1node2, attribute2Node2=attributeValue2node2, attribute3Node2=attributeValue3node2}}}
我在这里做错了什么?
答案 0 :(得分:0)
好吧,经过几个小时的挣扎,似乎这将进入任何深度的嵌套地图并构建XML。可能不是我看起来最犹太的代码,但它会做。
static def makeXmlBody(map, lastParent, counter) {
def writer = new StringWriter()
def xmlBuilder = new MarkupBuilder(writer)
if (counter == 0) {
xmlBuilder.mkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
}
counter++
map.each {
if (it.value.getClass() == LinkedHashMap) {
xmlBuilder.createNode(it.key, it.value.attributes, makeXmlBody(it.value.elements, lastParent, counter))
xmlBuilder.nodeCompleted(lastParent, it.key)
lastParent = it.key
} else {
xmlBuilder.createNode(it.key, it.value)
xmlBuilder.nodeCompleted(lastParent, it.key)
}
}
return StringEscapeUtils.unescapeXml(writer.toString())
}
使用
makeXmlBody(map, null, 0)
输出(美化)
<?xml version='1.0' encoding='utf-8'?>
<root rootAttribute='rootAttribute1'>
<node1 attribute1Node1='attributeValue1node1' attribute2Node1='attributeValue2node1'
attribute3Node1='attributeValue3node1'>
<key1Node1>elementValue1Node1</key1Node1>
<key2Node1>elementValue2Node2</key2Node1>
</node1>
<node2 attribute1Node2='attributeValue1node2' attribute2Node2='attributeValue2node2'
attribute3Node2='attributeValue3node2'>
<key1Node2>elementValue1Node2</key1Node2>
<key2Node2>elementValue2Node2</key2Node2>
</node2>
</root>