如何使用 go 处理多个 xml API 响应结果?

Posted

技术标签:

【中文标题】如何使用 go 处理多个 xml API 响应结果?【英文标题】:How to handle multiple xml API response results with go? 【发布时间】:2021-06-21 23:56:15 【问题描述】:

要处理一个 xml API 响应结果,需要捕获多个 case。对于成功案例和失败案例,我可以定义 2 个结构来处理它们。来源为:go playground。

如果响应数据有很多结果,并且它们没有相同的xml结构,我们可以在go中定义所有的struct类型。但是有没有一种简单的方法来捕获它的数据?

我发现go的xmlUnmarshalXML方法可以重写xml数据。 Package xml 但是使用它需要先设置为特殊且唯一的结构:

func (r *PostSuccessResponse) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error 

    return nil

是否可以使用startElement.Name.Local 遍历所有响应xml 数据以检查它有什么元素,然后使用哪个go 结构来处理?如找到Fault则使用PostFailureResponse结构体,如果找到return则使用PostSuccessResponse结构体。

【问题讨论】:

而不是使用UnmarshalXML,你考虑过这个吗? play.golang.org/p/EQla8IYkw3n @mkopriva 看起来不错。谢谢! 【参考方案1】:

根据 cmets 的建议,我重新创建了您的代码,如下所示:

package main

import (
    "encoding/xml"
    "fmt"
)

type PostSuccessResponse struct 
    PostID     string `xml:"return>postResult>postId"`
    PostNumber string `xml:"return>postNumber"`


type PostFailureResponse struct 
    Code    string `xml:"detail>faultDetails>code"`
    Details string `xml:"detail>faultDetails>details"`


type Response struct 
    PostSuccessResponse *PostSuccessResponse `xml:"Body>postResponse"`
    PostFailureResponse *PostFailureResponse `xml:"Body>Fault"`


func main() 
    var response1 = &Response
    if err := xml.Unmarshal([]byte(successPayload), response1); err != nil 
        panic(err)
    
    fmt.Printf("success=%+v failure=%+v\n", response1.PostSuccessResponse, response1.PostFailureResponse)

    var response2 = &Response
    if err := xml.Unmarshal([]byte(failurePayload), response2); err != nil 
        panic(err)
    
    fmt.Printf("success=%+v failure=%+v\n", response2.PostSuccessResponse, response2.PostFailureResponse)


var successPayload = []byte(`
    <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
       <env:Header/>
       <env:Body>
          <ns2:postResponse xmlns:ns2="http://example.com/">
             <return>
                <postDetails>
                    <title>P</title>
                    <body>A</body>
                </postDetails>
                <postResult>
                   <postId>1234</postId>
                </postResult>
                <postNumber>1000000</postNumber>
             </return>
          </ns2:postResponse>
       </env:Body>
    </env:Envelope>
`)

var failurePayload = []byte(`
    <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
       <env:Header/>
       <env:Body>
          <env:Fault>
             <faultcode>env:Server</faultcode>
             <faultstring>An unexpected problem occurred</faultstring>
             <detail>
                <ns2:faultDetails xmlns:ns2="http://example.com/">
                   <code>Unexpected error</code>
                   <details>The post content is not right.</details>
                </ns2:faultDetails>
             </detail>
          </env:Fault>
       </env:Body>
    </env:Envelope>
`)

输出:

success=&PostID:1234 PostNumber:1000000 failure=<nil>
success=<nil> failure=&Code:Unexpected error Details:The post content is not right.

【讨论】:

使用相同的代码,我得到不同的输出:playground

以上是关于如何使用 go 处理多个 xml API 响应结果?的主要内容,如果未能解决你的问题,请参考以下文章

Go语言 Gin处理响应

Go语言 Gin处理响应

如何从 googleapi Youtube API 获取 XML 响应

我如何编写处理来自 API 的响应/错误的 golang 中间件?

如何使用 asyncio 和 aiohttp 异步通过 api 响应进行分页

如何在Python中将API响应时间减少89.30%