提升多层级的嵌套结构数组以进行 XML 解码。

huangapple go评论79阅读模式
英文:

Promote nested array of struct by multi level for XML decoding

问题

我有一个嵌套结构的结构体,格式如下,我提升了在结构体数组中的News结构体,它在结构体数组URL中。

我的RSS订阅源是:https://foreignpolicy.com/feed/

这是我用来从我的RSS订阅源生成Go结构体的工具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"`
}

这是Goplayground提升News结构体的示例

我想进一步提升Channel中的所有内容,这样我就可以直接从最顶层的Rss结构体中访问News结构体中的项:

type Rss struct {
    XMLName xml.Name `xml:"rss"`
    Channel --> 似乎不起作用
}
type Channel struct {
    URL []struct {
        News
    }
}
type News struct {
    Loc         string `xml:"channel>item>link"` --> 这是正确的XML标签吗
    Publishdate string `xml:"pubDate"` --> 还是这是正确的XML标签
    Title       string `xml:"title"`
    Summary     string `xml:"description"`
}

这样我就可以按如下方式打印:

var URLset Rss
if xmlBytes, err := getXML(url); err != nil {
    fmt.Printf("Failed to get XML: %v", err)
} else {
    xml.Unmarshal(xmlBytes, &URLset)
}
/************************** XML解析器 *************************/
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")
}

但似乎没有打印任何内容
Goplayground提升Channel的示例

英文:

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

答案1

得分: 2

你可以这样做:

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

并且从Loc的标签中移除channel>item


[]struct{ }中嵌入News类型似乎是多余的。所以你可以这样做:

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

你将得到相同的结果。


我建议你使用与XML元素名称匹配的名称,例如使用Item代替News,使用Items代替URL

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

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


关于结构标签中的>xml.Unmarshal文档中有以下说明:

> 如果XML元素包含一个子元素,其名称与标记格式为“a”或“a>b>c”的前缀匹配,unmarshal将进入XML结构,寻找具有给定名称的元素,并将最内层的元素映射到该结构字段。以“>”开头的标记等效于以字段名称开头,后跟“>”。

https://pkg.go.dev/encoding/xml@go1.18.2#Unmarshal

英文:

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/xml@go1.18.2#Unmarshal

huangapple
  • 本文由 发表于 2022年5月21日 12:39:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/72326710.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定