1 回答
TA贡献1802条经验 获得超5个赞
该响应不是有效的 XML 文档,因此您无法按原样一步或不进行修改/“修饰”对其进行解码。
以下解决方案用作body
未读响应正文流:Response.Body
。
1. 解码为一系列XML文档
然而,它可以被视为一系列XML文档,因此您可以用来xml.Decoder
逐一解码它们。
例如:
var res result
dec := xml.NewDecoder(body)
var err error
decField := func(v interface{}) {
if err == nil {
err = dec.Decode(v)
}
}
decField(&res.Status)
decField(&res.Statusmsg)
decField(&res.Vmstat)
decField(&res.Hostname)
decField(&res.Ipaddress)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%+v\n", res)
输出(在Go Playground上尝试):
{Status:success Statusmsg:online Vmstat:online Hostname:kvm-vps2 Ipaddress:123.456.789.99}
是的,逐场解码很不方便。
2. 读取正文并用根标签包装
另一种选择是用标签包装它,使其成为有效的 XML 文档:
buf := &bytes.Buffer{}
buf.WriteString("<root>")
if _, err := io.Copy(buf, body); err != nil {
panic(err)
}
buf.WriteString("</root>")
var res result
if err := xml.Unmarshal(buf.Bytes(), &res); err != nil {
panic(err)
}
fmt.Printf("%+v\n", res)
这输出相同。在Go Playground上尝试一下。
是的,上述解决方案必须首先将正文读入内存。
3. 包装主体流而不将其读入内存
不过,我们可以避免阅读并将正文保留在内存中。我们可以构建一个阅读器,在阅读时首先提供开始包装标签,然后提供“原始”主体,最后提供结束标签。为此,我们可以使用io.MultiReader()
:
r := io.MultiReader(
strings.NewReader("<root>"),
body,
strings.NewReader("</root>"),
)
var res result
if err := xml.NewDecoder(r).Decode(&res); err != nil {
panic(err)
}
fmt.Printf("%+v\n", res)
这再次输出相同的结果。在Go Playground上试试这个。
- 1 回答
- 0 关注
- 105 浏览
添加回答
举报