创建一个带有循环列表的地图 XML

Create a Map with Lists looping XML

我有一个我无法解决的需求。

我的 XML 如下所示

<root>
<node1>
<value1>AA</value1>
<value2>123</value2>
</node1>
<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>

我的要求是创建一个包含所有 value2 的地图。

输出应如下所示 [机管局:[123,999]] [AB:[456,888]]

我无法解决这个问题,需要帮助或指点please.I将需要检查 value1 字段在下一次迭代到下一个节点和存储中是否不同。

请帮忙。

代码可能如下所示:

import groovy.xml.*

def s = '''
<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 XmlParser().parseText(s)

def result = xml.'*'.inject( [:].withDefault{ [] } ){ res, node ->
  res[ node.value1.text() ] << node.value2.text()
  res
}

assert result == [AA:['123', '999'], AB:['456', '888']]

@injecteer 说的。

另一种方法涉及两个步骤,但可能更容易理解:

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

执行时打印:

─➤ groovy solution.groovy
[AA:[123, 999], AB:[456, 888]]

其中第一个 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 操作从节点中拉出 value2,留下 result 变量作为 Map<String, List<String>>

<<编辑>>

我意识到这个解决方案实际上使用了一个非常奇怪的 groovy “功能”,如果您调用 list.someProperty 并且 someProperty 不存在于列表 class 中(例如java.util.ArrayList), groovy 将 return 一个包含列表元素中所有 someProperty 值的列表。

如果我们想改变这个不使用我们可以做的怪事:

def result = xml.'*'.groupBy { 
  it.value1 
}.collectEntries { k, v -> 
  [k, v*.value2]
}

instead 它使用 the groovy spread operator 而不是未记录的怪异。

def xml = new XmlSlurper().parseText(data)

def result = xml.'*'.groupBy { 
  it.value1 
}.collectEntries { k, v -> 
  [k, v.value2]
}

这绝对有效。