You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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)
}

修改说明:

  1. 将EnvelopeResponse的Body字段类型从Message接口改为Body结构体,让xml.Unmarshal能明确解析目标。
  2. 给Body的Content字段添加xml:",any"标签,该标签会指示xml包将Body节点下所有未被显式匹配的子元素解析到这个接口字段中,完美适配动态接收不同SOAP响应内容的需求。
  3. 调整GetContent函数逻辑,先初始化EnvelopeResponse,再把传入的content指针赋值给envelope.Body.Content,确保解析时内容直接填充到你传入的结构体里。

运行后会输出预期结果:{{urn:dslforum-org:service:Hosts:1 GetHostNumberOfEntriesResponse} 47}

内容的提问来源于stack exchange,提问作者Marco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 20:00:16