Groovy XML映射分组重复键

发布于 2025-02-08 10:26:17 字数 634 浏览 4 评论 0原文

我有一个XML响应,希望将其转换为地图,但是某些XML节点是重复,因此我希望将它们转换为 地图列表。 目前,我正在使用此文章中建议的此代码: xmlslslurper-to-to-return-to-return-to-return-to-return-all-xml-all-xml-- a-map

预先感谢。

示例:

<head>test</head>
<tail>
    <name>1</name>
    <name>2</name>
</tail>
</body>

我想要以下地图:

["head" : "test" , "tail" : [["name":"1"],["name":"2"]]]

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"]]]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

埖埖迣鎅 2025-02-15 10:26:17

问题在于该代码:

nodes.children().collectEntries { 
    [it.name(), it.childNodes() ? convertToMap(it) : it.text() ] 
}

覆盖所得地图中的值。我没有设法在不做一些丑陋的黑客的情况下找到优雅的解决方案。但这是我的解决方案:

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
    }
}

我在这里做的是我首先收集所有孩子作为地图条目列表,因此看起来像[[key1:value1],[key2:value2]] 。然后,我循环浏览此中间结构并收集结果。

我希望它有助于前进。也许以后有人会以更好的解决方案来找您,因为正如我所说,目前我还没有找到任何优雅的方法来解决它。

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.

最丧也最甜 2025-02-15 10:26:17

经过一些挣扎之后,我编写了此代码来解决我的问题,我尝试使用MultivalUemap,但它正在转换所有值列出,因此我最终必须自己写作:

def xml = new groovy.xml.XmlSlurper().parse(response)
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
    }

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 groovy.xml.XmlSlurper().parse(response)
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
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文