亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何將沒有根/父元素的 XML 轉換為結構體?

如何將沒有根/父元素的 XML 轉換為結構體?

Go
回首憶惘然 2023-08-07 19:00:18
來自遠程服務器的 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 coder := result{}err = xml.Unmarshal(body, &r)// other code這里應該修復什么以便我可以訪問所有 API 響應值?
查看完整描述

1 回答

?
12345678_0001

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上試試這個。



查看完整回答
反對 回復 2023-08-07
  • 1 回答
  • 0 關注
  • 141 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號