猿问

如何将没有根/父元素的 XML 转换为结构体?

来自远程服务器的 API 响应(响应内容类型:text/html):


<status>success</status>

<statusmsg>online</statusmsg>

<vmstat>online</vmstat>

<hostname>kvm-vps2</hostname>

<ipaddress>123.456.789.99</ipaddress>

我尝试将上面的 API 响应解析为 Go 结构。我的以下方法均无效:


方法#1 代码


type result struct {

    Status    string `xml:",chardata"`

    Statusmsg string `xml:",chardata"`

    Vmstat    string `xml:",chardata"`

    Hostname  string `xml:",chardata"`

    Ipaddress string `xml:",chardata"`

}

方法#2 代码


type result struct {

    Status    string `xml:"status"`

    Statusmsg string `xml:"statusmsg"`

    Vmstat    string `xml:"vmstat"`

    Hostname  string `xml:"hostname"`

    Ipaddress string `xml:"ipaddress"`

}

从方法#1 中,我只获得了值Status。其他值均为空。对于方法#2,所有值都是空的。


解组代码:


// other code

r := result{}

err = xml.Unmarshal(body, &r)

// other code

这里应该修复什么以便我可以访问所有 API 响应值?


回首忆惘然
浏览 106回答 1
1回答

12345678_0001

该响应不是有效的 XML 文档,因此您无法按原样一步或不进行修改/“修饰”对其进行解码。以下解决方案用作body未读响应正文流:Response.Body。1. 解码为一系列XML文档然而,它可以被视为一系列XML文档,因此您可以用来xml.Decoder逐一解码它们。例如:var res resultdec := xml.NewDecoder(body)var err errordecField := 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 resultif 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 resultif err := xml.NewDecoder(r).Decode(&res); err != nil {    panic(err)}fmt.Printf("%+v\n", res)这再次输出相同的结果。在Go Playground上试试这个。
随时随地看视频慕课网APP

相关分类

Go
我要回答