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

问题描述

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

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

我发现 go 的 xml UnmarshalXML 方法可以重写 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结构体。

解决方法

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

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