首页 > Go解析XML出错,求指点?

Go解析XML出错,求指点?

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 stringxml:"ErrorNo,attr"`。

下面是修正过的 struct 定义,以及调用的例子。

gotype 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

【热门文章】
【热门文章】