代码之家  ›  专栏  ›  技术社区  ›  Peter Cook

Groovy中XML响应节点数据的映射

  •  1
  • Peter Cook  · 技术社区  · 6 年前

    我试图在映射中存储XML响应节点值,但这确实很复杂。以下是XML:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <SearchRS>
        <SearchStatus>SUCCESS</SearchStatus>
        <Itinerary>
            <Name>Joe</Name>
            <Ticket>111.11</Ticket>
            <Taxes>1.11</Taxes>
        </Itinerary>
        <Itinerary>
            <Name>Bob</Name>
            <Ticket>222.22</Ticket>
            <Taxes>2.22</Taxes>
        </Itinerary>
        <Itinerary>
            <Name>Joe</Name>
            <Ticket>333.33</Ticket>
            <Taxes>3.33</Taxes>
            </Itinerary>
        <Itinerary>
        <Itinerary>
            <Name>Bob</Name>
            <Ticket>444.44</Ticket>
            <Taxes>4.44</Taxes>
        </Itinerary>
            <Name>Joe</Name>
            <Ticket>0.0</Ticket>
            <Taxes>0.0</Taxes>
        </Itinerary>
    </SearchRS>
    

    我需要计算每个名字的平均门票+税款。

    注:0.0的任何值都应从平均值中排除。

    我想创建一个包含以下内容的地图:

    [ name : average of ticket+taxes value] 
    

    我试过了,这会找到每个的最小值,博士。日程表保存XML响应。

      def minByName = doc.Itinerary
                .inject([:].withDefault { [] }) { map, it ->
           map[it.Name.text()] << it
           map
      }
      .collectEntries { profile, nodes ->
           [profile, nodes.min { it.Ticket.text() as Double }]
      }
    
      def nameList = []
        minByName.each { profile, minimum ->
            Map nameMap = [:]
            nameMap.name = profile
            nameMap.ticket = minimum.Ticket.toString()
            nameMap.taxes = minimum?.Taxes
            nameList << nameMap
      }
     log.info("Cheapest ticket and tax per name: " + nameList)
    

    这将导致每个名称都有一组数据:

    [[name:Joe, ticket:111.11, taxes:1.11], [name:Bob, etc...]]
    

    我希望地图中的值不是最小值,而是平均值,例如,Joe的所有门票+税款。

    如下所示:

    [[name:Joe, averageCost:224.44], [name:Bob, averageCost...]]
    

    111.11+1.11=112.22,333.33+3.33=336.66。112.22+336.66=448.88。448.88/2=224.44

    我真的被困在这一点上了,非常感谢您的帮助!

    2 回复  |  直到 6 年前
        1
  •  1
  •   Rao CrashOverload    6 年前

    看看这是否是你想要的(在线评论中解释):

    //pass xmlString to below
    def xml = new XmlSlurper().parseText(xmlString)
    def map = [:]
    //Find unique names, then  respective Iteneraries, then collect ticket & taxes, convert to Double, eliminate 0 values, sum and average, put into map
    xml.'**'.findAll {it.name() == 'Name'}.unique().each { name -> 
       map[name] = xml.'**'.findAll {it.name() == 'Itinerary' && name == it.Name.text() }.collect { Double.parseDouble(it.Ticket.text()) + Double.parseDouble(it.Taxes.text())}.findAll {it}.with { sum() / size() }
    }
    println map
    

    请找到快捷键 demo

    编辑: 回应OP的评论。

    改变 sum() sum().round(2)

        2
  •  0
  •   Bhanuchander Udhayakumar    6 年前

    如果我理解正确,

    def root = new XmlSlurper().parse(new File ('/tmp/stack.xml'))
    
    List <String> names = root.'**'.findAll{ it.name() == "Name"}.collect{it}
    
    List <Map> totalresult = []
    
    names.unique().each{name ->
    
        Map result = [:]
    
        result["name"] = name
    
        List<Float> tickets = root.'**'.findAll{ it.Name == name && it.Ticket.toFloat() > 0.0}.collect { it.Ticket.toFloat() + it.Taxes.toFloat() }
    
        result ["total"] = tickets.sum()
    
        result ["occurances"]= tickets.size()
    
        result ["avgCosts"] = result.total/result.occurances
    
        totalresult.add(result)
    
    }
    
    println totalresult
    

    更新1:根据要求更正代码。