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

时间:2015-12-17 11:56:15

标签: xml go

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的能力?

2 个答案:

答案 0 :(得分:4)

对于重复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 :(得分:0)

是的,您可以使用相同的名称编组/解组多个节点。只需使用切片。

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

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>

full example