package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
"os"
)
type Name struct {
XMLName xml.Name `xml:"DomainCheckResult"`
Domain string `xml:"Domain"`
Available string `xml:"Available"`
ErrorNo string `xml:"ErrorNo"`
}
type Names struct {
XMLName xml.Name `xml:"CommandResponse"`
Domains []Name `xml:"DomainCheckResult"`
}
func main() {
xmlFile, err := os.Open("data.xml")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer xmlFile.Close()
XMLdata, _ := ioutil.ReadAll(xmlFile)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
var d Names
xml.Unmarshal(XMLdata, &d)
fmt.Println(d.Domains)
}
XML File:
<ApiResponse xmlns="http://api.namecheap.com/xml.response" Status="OK">
<Errors/>
<Warnings/>
<RequestedCommand>namecheap.domains.check</RequestedCommand>
<CommandResponse Type="namecheap.domains.check">
<DomainCheckResult Domain="sap.com" Available="false" ErrorNo="0" Description=""/>
<DomainCheckResult Domain="ibm.com" Available="true" ErrorNo="0" Description=""/>
</CommandResponse>
<Server>PHX01SBAPI01</Server>
<GMTTimeDifference>--4:00</GMTTimeDifference>
<ExecutionTime>1.668</ExecutionTime>
</ApiResponse>
Output:
[{{ DomainCheckResult} } {{ DomainCheckResult} }]
首先题主应该检查一下 xml.Unmarshal(XMLdata, &d)
的返回值,通过这个就已经能明确的看出 xml.Unmarshal
其实失败了,返回了一个错误,告诉你这个 xml 的根是 ApiResponse
而非 CommandResponse
。
此外,如果要解析 xml 属性的话,需要在字段的 tag 里面写上 ,attr
,例如 ErrorNo string
xml:"ErrorNo,attr"`。
下面是修正过的 struct 定义,以及调用的例子。
go
type Name struct { XMLName xml.Name `xml:"DomainCheckResult"` Domain string `xml:"Domain,attr"` Available string `xml:"Available,attr"` ErrorNo string `xml:"ErrorNo,attr"` } type Names struct { XMLName xml.Name `xml:"CommandResponse"` Domains []Name `xml:"DomainCheckResult"` } type ApiResponse struct { XMLName xml.Name `xml:"ApiResponse"` Names Names `xml:"CommandResponse"` } func main() { // 省略读文件的部分…… var api ApiResponse xml.Unmarshal(XMLdata, &api) fmt.Println(api.Names.Domains) }
问题已解决:
package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
"os"
)
type Domain struct {
XMLName xml.Name `xml:"DomainCheckResult"`
Domain string `xml:"Domain,attr"`
Available string `xml:",attr"`
ErrorNo string `xml:",attr"`
Description string `xml:",attr"`
}
type Domains struct {
XMLName xml.Name `xml:"CommandResponse"`
Domains []Domain `xml:"DomainCheckResult"`
}
type ApiResponse struct {
XMLName xml.Name `xml:"ApiResponse"`
ApiResponse Domains
}
func main() {
xmlFile, err := os.Open("data.xml")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer xmlFile.Close()
XMLdata, _ := ioutil.ReadAll(xmlFile)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
var d ApiResponse
err = xml.Unmarshal(XMLdata, &d)
if err != nil {
fmt.Println(err)
}
for k, _ := range d.ApiResponse.Domains {
fmt.Printf("%s -> %s\n", d.ApiResponse.Domains[k].Domain, d.ApiResponse.Domains[k].Available)
}
// fmt.Printf(d.ApiResponse.Domains)
}
Output:
sap.com -> false
ibm.com -> true