在Go中解封SOAP响应

在Go中解封SOAP响应

问题描述:

I am making a SOAP call to an API, Here is a sample response:

<?xml version="1.0" encoding="utf-8" ?>
 <soapenv:envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:body>
      <soapenv:fault>
        <faultcode>
          ERR109
        </faultcode>
        <faultstring>
          Account Expired. Result code is 2163
        </faultstring>
        <detail>
          <ns1:serviceexception xmlns:ns1="http://www.csapi.org/schema/parlayx/common/v2_1">
            <messageid>
              ERR109
            </messageid>
            <text>
              Account Expired. Result code is 2163
            </text>
            <variables>
              2163
            </variables>
          </ns1:serviceexception>
        </detail>
      </soapenv:fault>
    </soapenv:body>
  </soapenv:envelope>

To unmarshal this response, I have built some structs:

type SoapResponse struct {
    Body    ResponseBody `soapenv:"body"`
}
type ResponseBody struct {
    Fault   Fault    `soapenv:"fault"`
}
type Fault struct {
    FaultCode   string `xml:"faultcode"`
    FaultString string `xml:"faultstring"`
    Detail      Detail `xml:"detail"`
}
type Detail struct {
    ServiceException ServiceException `ns1:"serviceexception"`
}
type ServiceException struct {
    ID          string `xml:"messageid"` 
    MessageText string `xml:"text"`
    ErrorCode   string `xml:"variables"`
}

And here is the code that does the unmarshaling part:

responseBody, _:= ioutil.ReadAll(resp.Body)
var soapResponse = new(SoapResponse)
err := xml.Unmarshal(responseBody, soapResponse)
    if err != nil {
        panic("Error!")
    }

The problem is that all soapResponse properties are populated just right, except for soapResponse.Body.Fault.Detail.ServiceException.ID which prints nothing.
I couldn't figure out why. Any help would be appreciated.

You may parse got XML with such structures:

type SoapResponse struct {
    Body ResponseBody `xml:"soapenv body"`
}
type ResponseBody struct {
    Fault Fault `xml:"fault"`
}
type Fault struct {
    FaultCode   string `xml:"faultcode"`
    FaultString string `xml:"faultstring"`
    Detail      Detail `xml:"detail"`
}
type Detail struct {
    ServiceException ServiceException `xml:"serviceexception"`
}
type ServiceException struct {
    ID          string `xml:"messageid"`
    MessageText string `xml:"text"`
    ErrorCode   string `xml:"variables"`
}

I've added namespace for the first element and fixed some definitions. Working example - https://play.golang.org/p/vZQhaxYikX