What @injecteer said.
Another way involves two steps but might be easier to comprehend:
import groovy.xml.*
def data = '''
<root>
<node1>
<value1>AA</value1>
<value2>123</value2>
</node1>
<node2>
<value1>AA</value1>
<value2>999</value2>
</node2>
<node3>
<value1>AB</value1>
<value2>456</value2>
</node3>
<node4>
<value1>AB</value1>
<value2>888</value2>
</node4>
</root>'''
def xml = new XmlSlurper().parseText(data)
def result = xml.'*'.groupBy {
it.value1
}.collectEntries { k, v ->
[k, v.value2]
}
println result
which, when executed, prints:
─➤ groovy solution.groovy
[AA:[123, 999], AB:[456, 888]]
where the first groupBy
creates a Map<String, List<xml node>>
where the keys are the AA
, AB
strings and the values are the xml nodes. The second collectEntries
operation pulls out value2
from the nodes leaving the result
variable as a Map<String, List<String>>
.
<< edit >>
I realized this solution actually uses a really weird groovy "feature" where if you call list.someProperty
and someProperty
does not exist on the list class (like java.util.ArrayList
), groovy will return a list with all the someProperty
values from the list elements.
If we want to change this to not use that weirdness we can do:
def result = xml.'*'.groupBy {
it.value1
}.collectEntries { k, v ->
[k, v*.value2]
}
instead which uses the groovy spread operator instead of the undocumented weirdness.