我有一个关于如何遍历XML API响应并收集数据的问题。
假设我收到了XML格式的API回复。回复看起来像这样;
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SearchRS>
<SearchStatus>SUCCESS</SearchStatus>
<Itinerary>
<DisplayTotal>189.41</DisplayTotal>
<FareStarProfileID>11PUB2</FareStarProfileID>
</Itinerary>
<Itinerary>
<DisplayTotal>19.41</DisplayTotal>
<FareStarProfileID>11PUB3</FareStarProfileID>
</Itinerary>
<Itinerary>
<DisplayTotal>79.11</DisplayTotal>
<FareStarProfileID>11PUB8</FareStarProfileID>
</Itinerary>
<Itinerary>
<DisplayTotal>89.61</DisplayTotal>
<FareStarProfileID>11PUB4</FareStarProfileID>
</Itinerary>
</SearchRS>
现在我可以遍历这些门票并轻松完成诸如找到最高价,最低价和平均价,获取每个地点的总数等等,方法是:
def doc = new XmlSlurper().parseText(xmlResponse)
doc.Ticket.each { Ticket ->
// for each ticket in the xml response
Ticket.children().each { tag ->
// for each tag within each ticket
switch(tag.name()) {
case "Price":
[compute some stuff here]
case "Location":
[compute some stuff here]
etc....
如果我想找出每个FareStarProfileId最便宜的DisplayTotal,我的问题是什么?最简单的方法是什么?
答案 0 :(得分:0)
所以给出了一些像这样的XML:
def xmlResponse = '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SearchRS>
<SearchStatus>SUCCESS</SearchStatus>
<Itinerary>
<DisplayTotal>189.41</DisplayTotal>
<FareStarProfileID>11PUB2</FareStarProfileID>
</Itinerary>
<Itinerary>
<DisplayTotal>19.41</DisplayTotal>
<FareStarProfileID>11PUB3</FareStarProfileID>
</Itinerary>
<Itinerary>
<DisplayTotal>79.11</DisplayTotal>
<FareStarProfileID>11PUB8</FareStarProfileID>
</Itinerary>
<Itinerary>
<DisplayTotal>89.61</DisplayTotal>
<FareStarProfileID>11PUB4</FareStarProfileID>
</Itinerary>
</SearchRS>'''
您可以使用groupBy
和min
来实现此目标:
def doc = new XmlSlurper().parseText(xmlResponse)
// Group Itinerary by profile text, then for each profile, just keep
// the lowest price one
def minTotals = doc.Itinerary.groupBy { it.FareStarProfileID.text() }
.collectEntries { profile, nodes ->
[profile, nodes.min { it.DisplayTotal.text() as Double }]
}
// minTotals is a map of FareStarProfileID -> xml node representing the itinerary...
// Lets print them out
minTotals.each { profile, minimum ->
println "For profile $profile, the minimum is ${minimum.DisplayTotal}"
}
你无法在2.0.8中使用NodeChildren,所以你必须切换到使用inject
代替groupBy
def minTotals = doc.Itinerary
.inject([:].withDefault { [] }) { map, it ->
map[it.FareStarProfileID.text()] << it
map
}
.collectEntries { profile, nodes ->
[profile, nodes.min { it.DisplayTotal.text() as Double }]
}