使用Go反序列化SOAP消息:动态Body内容解析遇阻
这段代码反序列化SOAP消息没得到预期结果,核心问题有三个:
- EnvelopeResponse里的Body字段用了Message接口类型,Go的
xml.Unmarshal处理接口时无法自动确定解析的具体类型,得换成明确的Body结构体。 - Body结构体的Content字段标签不对,要加上
xml:",any",才能让xml包把Body下的自定义响应内容解析到这个字段里。 - GetContent函数的初始化逻辑有问题,没有正确关联传入的content指针。
修改后的代码如下:
package main import ( "encoding/xml" "fmt" ) type Message interface{} type EnvelopeResponse struct { XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"` Body Body `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"` // 改为具体Body结构体类型 } type Body struct { XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"` Fault *Fault `xml:",omitempty"` Content Message `xml:",any"` // 使用",any"标签捕获Body下的未知子元素 } type Fault struct { XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault"` Code string `xml:"faultcode,omitempty"` String string `xml:"faultstring,omitempty"` Actor string `xml:"faultactor,omitempty"` Detail string `xml:"detail,omitempty"` } type GetHostNumberOfEntriesResponse struct { XMLName xml.Name `xml:"urn:dslforum-org:service:Hosts:1 GetHostNumberOfEntriesResponse"` NewHostNumberOfEntries int64 `xml:"NewHostNumberOfEntries"` } func GetContent(rawXml []byte, content interface{}) error { envelope := EnvelopeResponse{} envelope.Body.Content = content // 关联传入的内容指针 return xml.Unmarshal(rawXml, &envelope) } func main() { b := []byte(` <?xml version="1.0"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:GetHostNumberOfEntriesResponse xmlns:u="urn:dslforum-org:service:Hosts:1"> <NewHostNumberOfEntries>47</NewHostNumberOfEntries> </u:GetHostNumberOfEntriesResponse> </s:Body> </s:Envelope> `) content := &GetHostNumberOfEntriesResponse{} if err := GetContent(b, content); err != nil { fmt.Println("解析失败:", err) return } fmt.Println(*content) }
修改说明:
- 将EnvelopeResponse的Body字段类型从Message接口改为Body结构体,让
xml.Unmarshal能明确解析目标。 - 给Body的Content字段添加
xml:",any"标签,该标签会指示xml包将Body节点下所有未被显式匹配的子元素解析到这个接口字段中,完美适配动态接收不同SOAP响应内容的需求。 - 调整GetContent函数逻辑,先初始化EnvelopeResponse,再把传入的content指针赋值给envelope.Body.Content,确保解析时内容直接填充到你传入的结构体里。
运行后会输出预期结果:{{urn:dslforum-org:service:Hosts:1 GetHostNumberOfEntriesResponse} 47}
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

