Beego需手动读取RequestBody并用xml.Unmarshal解析XML请求体,返回XML必须赋结构体指针给c.Data["xml"]后调用ServeXML();字段须导出且含xml标签,否则静默丢弃或解析失败。

Beego 支持原生 XML 解析与输出,但默认不自动处理 XML 请求体,需手动读取并反序列化;返回 XML 则必须显式调用 ServeXML(),且数据需为结构体指针。
如何接收并解析 XML 请求体
Beego 不像处理 JSON 那样自动解析 XML body,this.Input().Get("xxx") 对 XML 无效。你得自己读取原始 body 并用 xml.Unmarshal() 解析:
- 确保请求 header 中
Content-Type是application/xml或text/xml - 用
this.Ctx.Input.RequestBody获取原始字节流(不是this.Ctx.Request.Body,后者可能已被读过) - 定义带
xmltag 的结构体,注意字段首字母必须大写,否则无法被反序列化 - 别忘了检查
err,空 body、格式错误、嵌套缺失都会导致解析失败
示例:
type User struct {
ID int `xml:"id"`
Name string `xml:"name"`
Email string `xml:"email"`
}
func (c *MainController) Post() {
var u User
if err := xml.Unmarshal(c.Ctx.Input.RequestBody, &u); err != nil {
c.Ctx.ResponseWriter.WriteHeader(400)
c.Ctx.WriteString("invalid xml: " + err.Error())
return
}
// u 现在已填充
}
如何返回 XML 响应(ServeXML)
Beego 提供 ServeXML() 方法,它会把 c.Data["xml"] 中的值序列化为 XML 并设置 Content-Type: application/xml。关键点:
- 必须把结构体指针赋给
c.Data["xml"],传值或 map 会 panic - 结构体字段需有
xmltag,否则生成的 XML 字段名是 Go 字段名(全大写),不符合常规命名习惯 -
ServeXML()默认不缩进;若要美化输出,需手动设置BConfig.RunMode != "prod"或改源码(无公开参数控制) - 不能和
TplName混用——一旦调用了ServeXML(),模板渲染就失效了
示例:
func (c *MainController) Get() {
user := &User{ID: 123, Name: "Alice", Email: "a@example.com"}
c.Data["xml"] = user
c.ServeXML()
}
常见错误:XML 输出乱码或格式异常
典型现象是响应中出现中文乱码、根元素名不对、或整个响应变成空字符串。原因多为:
- 结构体字段没加
xmltag,导致序列化时字段被忽略(Go 默认忽略小写字段,且无 tag 时不会导出) - 用了
c.Ctx.WriteString(string(xmlBytes))手动输出,但没设Content-Type,浏览器/客户端当 HTML 或 text/plain 解析 - 结构体里嵌套了
interface{}或 map,xml包不支持直接序列化它们 - XML 声明缺失(如
<?xml version="1.0" encoding="UTF-8"?>)——xml.Marshal()默认不加,ServeXML()也不加,需自行拼接
修复建议:优先用 ServeXML() + 正确 tag 结构体;若必须手动输出,记得加 header:
c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/xml; charset=utf-8")
c.Ctx.WriteString(`<?xml version="1.0" encoding="UTF-8"?>` + string(xmlBytes))
XML 的 tag 控制比 JSON 细腻,比如 xml:",omitempty"、xml:"name>inner" 等,但 Beego 自身不介入这部分逻辑,完全由 Go 标准库 encoding/xml 决定。最容易被忽略的是:所有参与 XML 序列化的字段,必须是导出字段(首字母大写)且有明确 xml tag,否则静默丢弃。


















