I have a xml response and i want it to be converted to a map but some xml nodes are duplicate so i want those to be converted to List of maps. Currently I'm using this code suggested in this post : xmlslurper-to-return-all-xml-elements-into-a-map
Thanks in advance.
Sample :
<head>test</head>
<tail>
<name>1</name>
<name>2</name>
</tail>
</body>
and I want the following map :
["head" : "test" , "tail" : [["name":"1"],["name":"2"]]]
CodePudding user response:
The problem is that this piece of code:
nodes.children().collectEntries {
[it.name(), it.childNodes() ? convertToMap(it) : it.text() ]
}
overrides the value in the resulting map. I didn't manage to find an elegant solution to it without doing some ugly hacks. But here is my solution:
final xml = """
<body>
<head>test</head>
<test>
<child>Child</child>
</test>
<tail>
<name>1</name>
<name>2</name>
<name>3</name>
<name>4</name>
<name>5</name>
</tail>
</body>
"""
def slurper = new XmlSlurper().parseText(xml)
println convertToMap(slurper)
def convertToMap(nodes) {
final list = []
final children = nodes.children().iterator()
while (children.hasNext()) {
final child = children.next()
list << [(child.name()): child.childNodes() ? convertToMap(child) : child.text()]
}
final keys = list.collect { it.keySet()[0].toString() }
if (keys.size() == keys.unique().size()) {
list.collectEntries { [(it.keySet()[0]): it[it.keySet()[0]]] }
} else {
list
}
}
What I'm doing here is that I first collect all the children as list of map entries, so it looks like [[key1:value1], [key2:value2]]
. Then I loop over this intermediate structure and gather the results.
I hope it helps to move forward. Maybe later someone will come to you with a better solution, because as I said, at the moment I haven't found any elegant way to solve it.
CodePudding user response:
After some struggling I wrote this code to solve my problem, I tried to use MultiValueMap either but it was converting all the values to list so Finally I had to write in on my own :
def xml = new XmlSlurper().parse(response) // from groovy.util
convertToMap(xml)
def convertToMap(nodes) {
def map = [:]
nodes?.children()?.each {
def key = it.name()
def value = it.childNodes() ? convertToMap(it) : it.text()
if (map.containsKey(key)) {
def currentValue = map.get(key)
if (currentValue instanceof List) {
currentValue.add(value)
} else {
map.put(key, [currentValue, value])
}
} else {
map.put(key, value)
}
}
map
}