Home > OS >  Promote nested array of struct by multi level for XML decoding
Promote nested array of struct by multi level for XML decoding

Time:05-23

I have a struct with nested array of struct in format below, I have promoted News struct which is in struct array URL

My RSS Feed is : https://foreignpolicy.com/feed/

Here is the tool I used to generate Go struct from my RSS feed XML to Go struct

type Rss struct {
    XMLName xml.Name `xml:"rss"`
    Channel struct {
        URL []struct {
            News
        } `xml:"item"`
    } `xml:"channel"`
}
type News struct {
    Loc         string `xml:"link"`
    Publishdate string `xml:"pubDate"`
    Title       string `xml:"title"`
    Summary     string `xml:"description"`
}

Here is the Goplayround promote News struct

I want to go one step further to promote everything in Channel , so that I can access items in News struct directly from top most Rss struct:

type Rss struct {
    XMLName xml.Name `xml:"rss"`
    Channel --> seem NOT working ?
}
type Channel struct {
    URL []struct {
        News
    }
}
type News struct {
    Loc         string `xml:"channel>item>link"` ---> is it the right xml tag ?
    Publishdate string `xml:"pubDate"` ---> or this is the right xml tag ?
    Title       string `xml:"title"`
    Summary     string `xml:"description"`
}

So I can print it as below :

var URLset Rss
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("URLElement:", URLElement)
    fmt.Println(
        "[Element]:",
        "\nTitle #", URLElement.Title,
        "\nPublicationDate #", URLElement.Publishdate,
        "\nSummary#", URLElement.Summary,
        "\nLoc #", URLElement.Loc,
        "\n")
}

But it seems print nothing Goplayground Promote Channel

CodePudding user response:

You can do

URL []struct { News } `xml:"channel>item"`

and remove the channel>item from the Loc's tag.


The embedding of the News type in []struct{ } seems superfluous. So you can instead do

URL []News `xml:"channel>item"`

and you'll get the same result.


And I'd recommend that you use names that match the XML's element names, i.e. Item instead of News and Items instead of URL.

Items []Item `xml:"channel>item"`

https://go.dev/play/p/1Ig7wtxckqJ


The xml.Unmarshal documentation on > in struct tags says the following:

If the XML element contains a sub-element whose name matches the prefix of a tag formatted as "a" or "a>b>c", unmarshal will descend into the XML structure looking for elements with the given names, and will map the innermost elements to that struct field. A tag starting with ">" is equivalent to one starting with the field name followed by ">".

https://pkg.go.dev/encoding/[email protected]#Unmarshal

  • Related