英文:
XML Marshalling with Golang - Multiple Nodes with Identical Node Name
问题
在VAST规范中,一个XML文件可以包含多个具有相同名称的节点,例如多个Impression
节点,它们只在其id
属性上有所不同。
考虑以下示例:
<?xml version="1.0" encoding="UTF-8"?>
<VAST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:noNamespaceSchemaLocation="vast.xsd">
<Ad id="812030">
<InLine>
<AdSystem>FT</AdSystem>
<AdTitle>Flashtalking mobile vast template 2.0</AdTitle>
<Description>date of revision 10-04-14</Description>
<Impression id="ft_vast_i"><![CDATA[http://servedby.flashtalking.com/imp/1/31714;812030;201;gif;DailyMail;640x360VASTHTML5/?ft_creative=377314&ft_configuration=0&cachebuster=1076585830]]></Impression>
<Impression id="3rdparty" />
<Impression id="3rdparty" />
<Impression id="3rdparty" />
<Impression id="3rdparty" />
<Impression id="3rdparty" />
<Impression id="3rdparty" />
<Creatives>
<Creative sequence="1">
<Linear>
<Duration>00:00:15</Duration>
<TrackingEvents>
<Tracking event="start"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-13-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="midpoint"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-15-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="firstQuartile"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-14-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="thirdQuartile"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-16-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="complete"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-17-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="mute"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-38-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="fullscreen"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-313-0-27565A88066DCD-1076585830]]></Tracking>
</TrackingEvents>
<VideoClicks>
<ClickThrough><![CDATA[http://servedby.flashtalking.com/click/1/31714;812030;377314;211;0/?random=1076585830&ft_width=640&ft_height=360&url=http://www.google.co.uk]]></ClickThrough>
</VideoClicks>
<MediaFiles>
<MediaFile id="1" delivery="progressive" type="video/mp4" bitrate="524" width="640" height="360"><![CDATA[http://cdn.flashtalking.com/17601/30988_26752_WacoClub_640x360_384kbps.mp4]]></MediaFile>
</MediaFiles>
</Linear>
</Creative>
<Creative sequence="1">
<CompanionAds />
</Creative>
</Creatives>
</InLine>
</Ad>
</VAST>
请注意,多个Impression
节点仅在其id
属性上有所不同(实际上,有时甚至可能相同)。
有没有一种方法可以使用Golang表示这样的结构,并保持使用encoding/xml
包进行XML的编组和解组的能力?
英文:
In VAST spec, an XML file may contains several nodes with the same name - for example, several Impression
nodes, which differ only in their id
.
Consider the following example:
<?xml version="1.0" encoding="UTF-8"?>
<VAST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:noNamespaceSchemaLocation="vast.xsd">
<Ad id="812030">
<InLine>
<AdSystem>FT</AdSystem>
<AdTitle>Flashtalking mobile vast template 2.0</AdTitle>
<Description>date of revision 10-04-14</Description>
<Impression id="ft_vast_i"><![CDATA[http://servedby.flashtalking.com/imp/1/31714;812030;201;gif;DailyMail;640x360VASTHTML5/?ft_creative=377314&ft_configuration=0&cachebuster=1076585830]]></Impression>
<Impression id="3rdparty" />
<Impression id="3rdparty" />
<Impression id="3rdparty" />
<Impression id="3rdparty" />
<Impression id="3rdparty" />
<Impression id="3rdparty" />
<Creatives>
<Creative sequence="1">
<Linear>
<Duration>00:00:15</Duration>
<TrackingEvents>
<Tracking event="start"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-13-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="midpoint"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-15-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="firstQuartile"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-14-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="thirdQuartile"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-16-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="complete"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-17-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="mute"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-38-0-27565A88066DCD-1076585830]]></Tracking>
<Tracking event="fullscreen"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-313-0-27565A88066DCD-1076585830]]></Tracking>
</TrackingEvents>
<VideoClicks>
<ClickThrough><![CDATA[http://servedby.flashtalking.com/click/1/31714;812030;377314;211;0/?random=1076585830&ft_width=640&ft_height=360&url=http://www.google.co.uk]]></ClickThrough>
</VideoClicks>
<MediaFiles>
<MediaFile id="1" delivery="progressive" type="video/mp4" bitrate="524" width="640" height="360"><![CDATA[http://cdn.flashtalking.com/17601/30988_26752_WacoClub_640x360_384kbps.mp4]]></MediaFile>
</MediaFiles>
</Linear>
</Creative>
<Creative sequence="1">
<CompanionAds />
</Creative>
</Creatives>
</InLine>
</Ad>
</VAST>
Note the multiple Impression
nodes which differ only by their id
attribute (and in fact even that may sometime be identical).
Is there a way to represent such structure with Golang in a way that will maintain the ability to marshal and unmarshal the xml with the encoding/xml
package?
答案1
得分: 6
对于重复的 XML 标签,在 Go 中可以简单地使用切片。
看下面这个简单的例子,它处理了你的 XML 输入,专注于解组 <Impression>
标签,然后再次编组它们:
type Impression struct {
Id string `xml:"id,attr"`
Content string `xml:",chardata"`
}
type VAST struct {
Impressions []Impression `xml:"Ad>InLine>Impression"`
}
func main() {
v := &VAST{}
if err := xml.Unmarshal([]byte(src), v); err != nil {
panic(err)
}
fmt.Printf("%+v\n\n", v)
if out, err := xml.MarshalIndent(v, "", " "); err != nil {
panic(err)
} else {
fmt.Println(string(out))
}
}
输出结果(换行显示,可以在 Go Playground 上尝试):
&{Impressions:[{Id:ft_vast_i Content:http://servedby.fla...[CUT]...1076585830}
{Id:3rdparty Content:} {Id:3rdparty Content:} {Id:3rdparty Content:}
{Id:3rdparty Content:} {Id:3rdparty Content:} {Id:3rdparty Content:}]}
<VAST>
<Ad>
<InLine>
<Impression id="ft_vast_i">http://servedby.fla...[CUT]...1076585830</Impression>
<Impression id="3rdparty"></Impression>
<Impression id="3rdparty"></Impression>
<Impression id="3rdparty"></Impression>
<Impression id="3rdparty"></Impression>
<Impression id="3rdparty"></Impression>
<Impression id="3rdparty"></Impression>
</InLine>
</Ad>
</VAST>
[1]: http://play.golang.org/p/JG0ontd6cO
英文:
For repeating XML tags, simply use a slice in Go.
See this simple example which handles your XML input focused on unmarshaling <Impression>
tags, then marshaling them again:
type Impression struct {
Id string `xml:"id,attr"`
Content string `xml:",chardata"`
}
type VAST struct {
Impressions []Impression `xml:"Ad>InLine>Impression"`
}
func main() {
v := &VAST{}
if err := xml.Unmarshal([]byte(src), v); err != nil {
panic(err)
}
fmt.Printf("%+v\n\n", v)
if out, err := xml.MarshalIndent(v, "", " "); err != nil {
panic(err)
} else {
fmt.Println(string(out))
}
}
Output (wrapped, try it on the Go Playground):
&{Impressions:[{Id:ft_vast_i Content:http://servedby.fla...[CUT]...1076585830}
{Id:3rdparty Content:} {Id:3rdparty Content:} {Id:3rdparty Content:}
{Id:3rdparty Content:} {Id:3rdparty Content:} {Id:3rdparty Content:}]}
<VAST>
<Ad>
<InLine>
<Impression id="ft_vast_i">http://servedby.fla...[CUT]...1076585830</Impression>
<Impression id="3rdparty"></Impression>
<Impression id="3rdparty"></Impression>
<Impression id="3rdparty"></Impression>
<Impression id="3rdparty"></Impression>
<Impression id="3rdparty"></Impression>
<Impression id="3rdparty"></Impression>
</InLine>
</Ad>
</VAST>
答案2
得分: 1
是的,你可以使用切片来编组/解组具有相同名称的多个节点。
看一下encoding/xml
示例中的Email
切片:
type Email struct {
Where string `xml:"where,attr"`
Addr string
}
type Address struct {
City, State string
}
type Result struct {
XMLName xml.Name `xml:"Person"`
Name string `xml:"FullName"`
Phone string
Email []Email
Groups []string `xml:"Group>Value"`
Address
}
对应的XML文档如下:
<Person>
<FullName>Grace R. Emlin</FullName>
<Company>Example Inc.</Company>
<Email where="home">
<Addr>gre@example.com</Addr>
</Email>
<Email where='work'>
<Addr>gre@work.com</Addr>
</Email>
<Group>
<Value>Friends</Value>
<Value>Squash</Value>
</Group>
<City>Hanga Roa</City>
<State>Easter Island</State>
</Person>
(完整示例)
英文:
Yes, you can marshal/unmarshal multiple nodes with the same names. Just use a slice.
Take a look at the Email
slice in the encoding/xml
example:
type Email struct {
Where string `xml:"where,attr"`
Addr string
}
type Address struct {
City, State string
}
type Result struct {
XMLName xml.Name `xml:"Person"`
Name string `xml:"FullName"`
Phone string
Email []Email
Groups []string `xml:"Group>Value"`
Address
}
And the corresponding XML document:
<Person>
<FullName>Grace R. Emlin</FullName>
<Company>Example Inc.</Company>
<Email where="home">
<Addr>gre@example.com</Addr>
</Email>
<Email where='work'>
<Addr>gre@work.com</Addr>
</Email>
<Group>
<Value>Friends</Value>
<Value>Squash</Value>
</Group>
<City>Hanga Roa</City>
<State>Easter Island</State>
</Person>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论