使用Golang进行XML编组 – 具有相同节点名称的多个节点

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

XML Marshalling with Golang - Multiple Nodes with Identical Node Name

问题

VAST规范中,一个XML文件可以包含多个具有相同名称的节点,例如多个Impression节点,它们只在其id属性上有所不同。

考虑以下示例:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <VAST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:noNamespaceSchemaLocation="vast.xsd">
  3. <Ad id="812030">
  4. <InLine>
  5. <AdSystem>FT</AdSystem>
  6. <AdTitle>Flashtalking mobile vast template 2.0</AdTitle>
  7. <Description>date of revision 10-04-14</Description>
  8. <Impression id="ft_vast_i"><![CDATA[http://servedby.flashtalking.com/imp/1/31714;812030;201;gif;DailyMail;640x360VASTHTML5/?ft_creative=377314&amp;ft_configuration=0&amp;cachebuster=1076585830]]></Impression>
  9. <Impression id="3rdparty" />
  10. <Impression id="3rdparty" />
  11. <Impression id="3rdparty" />
  12. <Impression id="3rdparty" />
  13. <Impression id="3rdparty" />
  14. <Impression id="3rdparty" />
  15. <Creatives>
  16. <Creative sequence="1">
  17. <Linear>
  18. <Duration>00:00:15</Duration>
  19. <TrackingEvents>
  20. <Tracking event="start"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-13-0-27565A88066DCD-1076585830]]></Tracking>
  21. <Tracking event="midpoint"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-15-0-27565A88066DCD-1076585830]]></Tracking>
  22. <Tracking event="firstQuartile"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-14-0-27565A88066DCD-1076585830]]></Tracking>
  23. <Tracking event="thirdQuartile"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-16-0-27565A88066DCD-1076585830]]></Tracking>
  24. <Tracking event="complete"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-17-0-27565A88066DCD-1076585830]]></Tracking>
  25. <Tracking event="mute"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-38-0-27565A88066DCD-1076585830]]></Tracking>
  26. <Tracking event="fullscreen"><![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-313-0-27565A88066DCD-1076585830]]></Tracking>
  27. </TrackingEvents>
  28. <VideoClicks>
  29. <ClickThrough><![CDATA[http://servedby.flashtalking.com/click/1/31714;812030;377314;211;0/?random=1076585830&amp;ft_width=640&amp;ft_height=360&amp;url=http://www.google.co.uk]]></ClickThrough>
  30. </VideoClicks>
  31. <MediaFiles>
  32. <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>
  33. </MediaFiles>
  34. </Linear>
  35. </Creative>
  36. <Creative sequence="1">
  37. <CompanionAds />
  38. </Creative>
  39. </Creatives>
  40. </InLine>
  41. </Ad>
  42. </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:

  1. &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
  2. &lt;VAST xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; version=&quot;2.0&quot; xsi:noNamespaceSchemaLocation=&quot;vast.xsd&quot;&gt;
  3. &lt;Ad id=&quot;812030&quot;&gt;
  4. &lt;InLine&gt;
  5. &lt;AdSystem&gt;FT&lt;/AdSystem&gt;
  6. &lt;AdTitle&gt;Flashtalking mobile vast template 2.0&lt;/AdTitle&gt;
  7. &lt;Description&gt;date of revision 10-04-14&lt;/Description&gt;
  8. &lt;Impression id=&quot;ft_vast_i&quot;&gt;&lt;![CDATA[http://servedby.flashtalking.com/imp/1/31714;812030;201;gif;DailyMail;640x360VASTHTML5/?ft_creative=377314&amp;ft_configuration=0&amp;cachebuster=1076585830]]&gt;&lt;/Impression&gt;
  9. &lt;Impression id=&quot;3rdparty&quot; /&gt;
  10. &lt;Impression id=&quot;3rdparty&quot; /&gt;
  11. &lt;Impression id=&quot;3rdparty&quot; /&gt;
  12. &lt;Impression id=&quot;3rdparty&quot; /&gt;
  13. &lt;Impression id=&quot;3rdparty&quot; /&gt;
  14. &lt;Impression id=&quot;3rdparty&quot; /&gt;
  15. &lt;Creatives&gt;
  16. &lt;Creative sequence=&quot;1&quot;&gt;
  17. &lt;Linear&gt;
  18. &lt;Duration&gt;00:00:15&lt;/Duration&gt;
  19. &lt;TrackingEvents&gt;
  20. &lt;Tracking event=&quot;start&quot;&gt;&lt;![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-13-0-27565A88066DCD-1076585830]]&gt;&lt;/Tracking&gt;
  21. &lt;Tracking event=&quot;midpoint&quot;&gt;&lt;![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-15-0-27565A88066DCD-1076585830]]&gt;&lt;/Tracking&gt;
  22. &lt;Tracking event=&quot;firstQuartile&quot;&gt;&lt;![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-14-0-27565A88066DCD-1076585830]]&gt;&lt;/Tracking&gt;
  23. &lt;Tracking event=&quot;thirdQuartile&quot;&gt;&lt;![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-16-0-27565A88066DCD-1076585830]]&gt;&lt;/Tracking&gt;
  24. &lt;Tracking event=&quot;complete&quot;&gt;&lt;![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-17-0-27565A88066DCD-1076585830]]&gt;&lt;/Tracking&gt;
  25. &lt;Tracking event=&quot;mute&quot;&gt;&lt;![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-38-0-27565A88066DCD-1076585830]]&gt;&lt;/Tracking&gt;
  26. &lt;Tracking event=&quot;fullscreen&quot;&gt;&lt;![CDATA[http://stat.flashtalking.com/reportV3/ft.stat?34923237-0-313-0-27565A88066DCD-1076585830]]&gt;&lt;/Tracking&gt;
  27. &lt;/TrackingEvents&gt;
  28. &lt;VideoClicks&gt;
  29. &lt;ClickThrough&gt;&lt;![CDATA[http://servedby.flashtalking.com/click/1/31714;812030;377314;211;0/?random=1076585830&amp;ft_width=640&amp;ft_height=360&amp;url=http://www.google.co.uk]]&gt;&lt;/ClickThrough&gt;
  30. &lt;/VideoClicks&gt;
  31. &lt;MediaFiles&gt;
  32. &lt;MediaFile id=&quot;1&quot; delivery=&quot;progressive&quot; type=&quot;video/mp4&quot; bitrate=&quot;524&quot; width=&quot;640&quot; height=&quot;360&quot;&gt;&lt;![CDATA[http://cdn.flashtalking.com/17601/30988_26752_WacoClub_640x360_384kbps.mp4]]&gt;&lt;/MediaFile&gt;
  33. &lt;/MediaFiles&gt;
  34. &lt;/Linear&gt;
  35. &lt;/Creative&gt;
  36. &lt;Creative sequence=&quot;1&quot;&gt;
  37. &lt;CompanionAds /&gt;
  38. &lt;/Creative&gt;
  39. &lt;/Creatives&gt;
  40. &lt;/InLine&gt;
  41. &lt;/Ad&gt;
  42. &lt;/VAST&gt;

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 输入,专注于解组 &lt;Impression&gt; 标签,然后再次编组它们:

  1. type Impression struct {
  2. Id string `xml:"id,attr"`
  3. Content string `xml:",chardata"`
  4. }
  5. type VAST struct {
  6. Impressions []Impression `xml:"Ad>InLine>Impression"`
  7. }
  8. func main() {
  9. v := &VAST{}
  10. if err := xml.Unmarshal([]byte(src), v); err != nil {
  11. panic(err)
  12. }
  13. fmt.Printf("%+v\n\n", v)
  14. if out, err := xml.MarshalIndent(v, "", " "); err != nil {
  15. panic(err)
  16. } else {
  17. fmt.Println(string(out))
  18. }
  19. }

输出结果(换行显示,可以在 Go Playground 上尝试):

  1. &{Impressions:[{Id:ft_vast_i Content:http://servedby.fla...[CUT]...1076585830}
  2. {Id:3rdparty Content:} {Id:3rdparty Content:} {Id:3rdparty Content:}
  3. {Id:3rdparty Content:} {Id:3rdparty Content:} {Id:3rdparty Content:}]}
  4. <VAST>
  5. <Ad>
  6. <InLine>
  7. <Impression id="ft_vast_i">http://servedby.fla...[CUT]...1076585830</Impression>
  8. <Impression id="3rdparty"></Impression>
  9. <Impression id="3rdparty"></Impression>
  10. <Impression id="3rdparty"></Impression>
  11. <Impression id="3rdparty"></Impression>
  12. <Impression id="3rdparty"></Impression>
  13. <Impression id="3rdparty"></Impression>
  14. </InLine>
  15. </Ad>
  16. </VAST>
  17. [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 &lt;Impression&gt; tags, then marshaling them again:

  1. type Impression struct {
  2. Id string `xml:&quot;id,attr&quot;`
  3. Content string `xml:&quot;,chardata&quot;`
  4. }
  5. type VAST struct {
  6. Impressions []Impression `xml:&quot;Ad&gt;InLine&gt;Impression&quot;`
  7. }
  8. func main() {
  9. v := &amp;VAST{}
  10. if err := xml.Unmarshal([]byte(src), v); err != nil {
  11. panic(err)
  12. }
  13. fmt.Printf(&quot;%+v\n\n&quot;, v)
  14. if out, err := xml.MarshalIndent(v, &quot;&quot;, &quot; &quot;); err != nil {
  15. panic(err)
  16. } else {
  17. fmt.Println(string(out))
  18. }
  19. }

Output (wrapped, try it on the Go Playground):

  1. &amp;{Impressions:[{Id:ft_vast_i Content:http://servedby.fla...[CUT]...1076585830}
  2. {Id:3rdparty Content:} {Id:3rdparty Content:} {Id:3rdparty Content:}
  3. {Id:3rdparty Content:} {Id:3rdparty Content:} {Id:3rdparty Content:}]}
  4. &lt;VAST&gt;
  5. &lt;Ad&gt;
  6. &lt;InLine&gt;
  7. &lt;Impression id=&quot;ft_vast_i&quot;&gt;http://servedby.fla...[CUT]...1076585830&lt;/Impression&gt;
  8. &lt;Impression id=&quot;3rdparty&quot;&gt;&lt;/Impression&gt;
  9. &lt;Impression id=&quot;3rdparty&quot;&gt;&lt;/Impression&gt;
  10. &lt;Impression id=&quot;3rdparty&quot;&gt;&lt;/Impression&gt;
  11. &lt;Impression id=&quot;3rdparty&quot;&gt;&lt;/Impression&gt;
  12. &lt;Impression id=&quot;3rdparty&quot;&gt;&lt;/Impression&gt;
  13. &lt;Impression id=&quot;3rdparty&quot;&gt;&lt;/Impression&gt;
  14. &lt;/InLine&gt;
  15. &lt;/Ad&gt;
  16. &lt;/VAST&gt;

答案2

得分: 1

是的,你可以使用切片来编组/解组具有相同名称的多个节点。

看一下encoding/xml示例中的Email切片:

  1. type Email struct {
  2. Where string `xml:"where,attr"`
  3. Addr string
  4. }
  5. type Address struct {
  6. City, State string
  7. }
  8. type Result struct {
  9. XMLName xml.Name `xml:"Person"`
  10. Name string `xml:"FullName"`
  11. Phone string
  12. Email []Email
  13. Groups []string `xml:"Group>Value"`
  14. Address
  15. }

对应的XML文档如下:

  1. <Person>
  2. <FullName>Grace R. Emlin</FullName>
  3. <Company>Example Inc.</Company>
  4. <Email where="home">
  5. <Addr>gre@example.com</Addr>
  6. </Email>
  7. <Email where='work'>
  8. <Addr>gre@work.com</Addr>
  9. </Email>
  10. <Group>
  11. <Value>Friends</Value>
  12. <Value>Squash</Value>
  13. </Group>
  14. <City>Hanga Roa</City>
  15. <State>Easter Island</State>
  16. </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:

  1. type Email struct {
  2. Where string `xml:&quot;where,attr&quot;`
  3. Addr string
  4. }
  5. type Address struct {
  6. City, State string
  7. }
  8. type Result struct {
  9. XMLName xml.Name `xml:&quot;Person&quot;`
  10. Name string `xml:&quot;FullName&quot;`
  11. Phone string
  12. Email []Email
  13. Groups []string `xml:&quot;Group&gt;Value&quot;`
  14. Address
  15. }

And the corresponding XML document:

  1. &lt;Person&gt;
  2. &lt;FullName&gt;Grace R. Emlin&lt;/FullName&gt;
  3. &lt;Company&gt;Example Inc.&lt;/Company&gt;
  4. &lt;Email where=&quot;home&quot;&gt;
  5. &lt;Addr&gt;gre@example.com&lt;/Addr&gt;
  6. &lt;/Email&gt;
  7. &lt;Email where=&#39;work&#39;&gt;
  8. &lt;Addr&gt;gre@work.com&lt;/Addr&gt;
  9. &lt;/Email&gt;
  10. &lt;Group&gt;
  11. &lt;Value&gt;Friends&lt;/Value&gt;
  12. &lt;Value&gt;Squash&lt;/Value&gt;
  13. &lt;/Group&gt;
  14. &lt;City&gt;Hanga Roa&lt;/City&gt;
  15. &lt;State&gt;Easter Island&lt;/State&gt;
  16. &lt;/Person&gt;

(full example)

huangapple
  • 本文由 发表于 2015年12月17日 19:56:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/34334008.html
匿名

发表评论

匿名网友

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

确定