Go:提升嵌套结构中的字段以进行 XML 解码

Go: promoted fields in nested struct for XML decoding

我有一个 XML 传输结构如下:

type urlset struct {
    XMLName xml.Name `xml:"urlset"`
    URL     []struct {
        Loc  string `xml:"loc"`
        News struct {
            Publishdate string `xml:"publication_date"`
            Title       string `xml:"title"`
            Summary     string `xml:"keywords"`
        } `xml:"news"`
    } `xml:"url"`
}

想在嵌套结构新闻中提升字段怎么办?

我希望我可以直接访问 News 的字段并打印如下值

var URLset urlset
if xmlBytes, err := getXML(url); err != nil {
    fmt.Printf("Failed to get XML: %v", err)
} else {
    xml.Unmarshal(xmlBytes, &URLset)
}
/************************** XML parser *************************/
for _, URLElement := range URLset.URL {
fmt.Println(
    "[Element]:",
    "\nTitle #", URLElement.title,
    "\nPublicationDate #", URLElement.Publishdate,
    "\nSummary#", URLElement.Summary,
        "\nLoc #", URLElement.Loc, "\n")
}

这是我的完整代码Go Playground

省略名称将嵌入自身。

例子

package main

import "fmt"

type Animal struct {
    Name string
}

type Cat struct {
    Animal //  Omit name
}

type Dog struct {
    A Animal //  have name "A"
}

func main() {
    cat := Cat{Animal{"Kitty"}}
    fmt.Println(cat.Name)        // OK
    fmt.Println(cat.Animal.Name) // OK too
    dog := Dog{Animal{"Snoopy"}}
    // fmt.Println(dog.Name)   // Error: type Dog has no field or method Name
    fmt.Println(dog.A.Name) // OK too
}

go playground


你的情况

</code>就够了(其他和你一样)</em></p> <pre><code>package main import ( "encoding/xml" "fmt" "io/ioutil" "net/http" ) type News struct { // move to here Publishdate string `xml:"news>publication_date"` // Use ">" to tell its parent. https://github.com/golang/go/blob/0a1a092c4b56a1d4033372fbd07924dad8cbb50b/src/encoding/xml/typeinfo.go#L198-L199 Title string `xml:"news>title"` Summary string `xml:"news>keywords"` } type urlset struct { XMLName xml.Name `xml:"urlset"` URL []struct { Loc string `xml:"loc"` News `xml:"news"` // do not give the name } `xml:"url"` } func getXML(url string) ([]byte, error) { resp, err := http.Get(url) if err != nil { return []byte{}, fmt.Errorf("GET error: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return []byte{}, fmt.Errorf("Status error: %v", resp.StatusCode) } data, err := ioutil.ReadAll(resp.Body) if err != nil { return []byte{}, fmt.Errorf("Read body: %v", err) } return data, nil } func main() { var URLset urlset /* To avoid the link not working in the future, I write the value directly. url := "https://www.dw.com/de/news-sitemap.xml" if xmlBytes, err := getXML(url); err != nil { fmt.Printf("Failed to get XML: %v", err) } else { xml.Unmarshal(xmlBytes, &URLset) } */ xmlBytes := []byte(` <urlset> <url> <loc>https://www.dw.com/de/kopf-an-kopf-rennen-bei-parlamentswahl-in-australien/a-61887162</loc> <news:news> <news:publication> <news:name>Deutsche Welle</news:name> <news:language>de</news:language> </news:publication> <news:publication_date>2022-05-21T11:28:55.875Z</news:publication_date> <news:title>Kopf-an-Kopf-Rennen bei Parlamentswahl in Australien</news:title> <news:keywords>Australien,Parlamentswahl,Scott Morrison,Anthony Albanese,Labor-Partei,Liberale</news:keywords> </news:news> <image:image> <image:loc>https://static.dw.com/image/61872101_403.jpg</image:loc> <image:caption>Der australische Premierminister Scott Morrison (r.) und sein Herausforderer, Oppositionsführer Anthony Albanese</image:caption> </image:image> </url> <url> <loc>https://www.dw.com/de/ukraine-aktuell-selenskyj-verlangt-entsch%C3%A4digungsfonds/a-61885143</loc> <news:news> <news:publication> <news:name>Deutsche Welle</news:name> <news:language>de</news:language> </news:publication> <news:publication_date>2022-05-21T11:10:21.813Z</news:publication_date> <news:title>Ukraine aktuell: Selenskyj verlangt Entschädigungsfonds</news:title> <news:keywords>Ukraine,Krieg,Russland,Wolodymyr Selenskyj,Wladimir Putin,Mariupol</news:keywords> </news:news> <image:image> <image:loc>https://static.dw.com/image/61885205_403.jpg</image:loc> <image:caption>75. Filmfestival Cannes | Rede von Wolodymyr Selenskyj</image:caption> </image:image> </url> <urlset> `) xml.Unmarshal(xmlBytes, &URLset) /************************** XML parser *************************/ for _, URLElement := range URLset.URL { /* fmt.Println( "[Element]:", "\nTitle #", URLElement.News.Title, "\nPublicationDate #", URLElement.News.Publishdate, "\nSummary#", URLElement.News.Summary, "\nLoc #", URLElement.Loc, "\n") */ fmt.Println( // Now, this work! "[Element]:", "\nTitle #", URLElement.Title, "\nPublicationDate #", URLElement.Publishdate, "\nSummary#", URLElement.Summary, "\nLoc #", URLElement.Loc, "\n") } }

关于 XML 命名空间

更多示例

  • ExampleUnmarshal这个link来自go/src/encoding/xml/example_test.go其实所有的例子都很容易理解。所以对学习有好处。