2017-02-23 66 views
2

我正在處理收到的XML,其中包含消息的無序列表,其中每個消息可以是幾種不同類型中的一種。訂單不重要。解組混合對象類型的xml數組

我制定了一個辦法做我想做的(多鬥爭,這是學習圍棋的第3天),但我掛了如何穩健意想不到的消息類型

這裏處理的一些代碼

package main 

import (
    "encoding/xml" 
    "fmt" 
) 

func main() { 

    data := `<Envelope> 
      <Body> 
       <Response> 
       <Messages> 
        <Greeting> 
        <From>Fred</From> 
        </Greeting> 
        <Reminder> 
        <Time>12</Time> 
        <Subject>Lunch at Joe's</Subject> 
        </Reminder> 
        <NewThing>Report me!</NewThing> 
        <Reminder> 
        <Time>6</Time> 
        <Subject>Catch the train</Subject> 
        </Reminder> 
        <Greeting> 
        <From>Mary</From> 
        <Extra>Hi</Extra> 
        </Greeting> 
       </Messages> 
       <MessageCount>3</MessageCount> 
       </Response> 
      </Body> 
      </Envelope>` 

    type Greeting struct { 
    From string 
    } 

    type Reminder struct { 
    Time int 
    Subject string 
    } 

    type TopLevel struct { 
    Messages struct { 
     GreetingList []Greeting `xml:"Greeting"` 
     ReminderList []Reminder `xml:"Reminder"` 
    } `xml:"Body>Response>Messages"` 
    } 

    var reply TopLevel 

    err := xml.Unmarshal([]byte(data), &reply) 
    if err != nil { 
    fmt.Println(err) 
    return 
    } 

    for _, reminder := range reply.Messages.ReminderList { 
    fmt.Printf("Reminder: '%s' at %d\n", reminder.Subject, reminder.Time) 
    } 

    for _, greeting := range reply.Messages.GreetingList { 
    fmt.Printf("Greetings From: %s\n", greeting.From) 
    } 

} 

輸出是

Reminder: 'Lunch at Joe's' at 12 
Reminder: 'Catch the train' at 6 
Greetings From: Fred 
Greetings From: Mary 

我也想能找到意想不到的消息類型既不是<Greeting>也不<Reminder>,例如<NewThing>,事先不知道任何關於新事物(等等)的東西。

Warning: Unexpected message type: NewThing. 

我應該想一些方法來獲得一個通用對象列表嗎?或者以某種方式使用XMLname + innerxml字符串的結構?不知道如何處理這些不同類型的單個列表。

線索?

回答

0

您可以使用, any, innerxml標籤處理意外的XML元素。

代碼變化(run full example at go playground

type Any struct { 
    XMLName xml.Name 
    Content string `xml:",innerxml"` 
    } 

    type TopLevel struct { 
    Messages struct { 
     GreetingList []Greeting `xml:"Greeting"` 
     ReminderList []Reminder `xml:"Reminder"` 
     UnexpectedList []Any  `xml:",any"` 
    } `xml:"Body>Response>Messages"` 
    } 

    ... 

    for _, unexpected := range reply.Messages.UnexpectedList { 
    fmt.Printf("Unexpected: %s containing '%s'\n", unexpected.XMLName, unexpected.Content) 
    } 

輸出

Reminder: 'Lunch at Joe's' at 12 
Reminder: 'Catch the train' at 6 
Greetings From: Fred 
Greetings From: Mary 
Unexpected: { NewThing} containing 'Report me!' 
Unexpected: { NewerThing} containing '<Fruit>Apple</Fruit><Sales>42</Sales>' 
2

我會質疑你在解碼JSON和Go時閱讀這個blog post。 「帶接口{}的通用JSON」,「解碼任意數據」和「引用類型」部分解決了您正在尋求解決的問題。

還請記住,上述方法是非常裸露的骨頭。我更喜歡在現實世界中使用更高級別的庫。我知道你在看XML,但在JSON場景中,我使用了jason,結果很好。

+0

我無法理解'接口{}'。 將XML編組到'interface {}中,我得到[''](https://play.golang.org/p/QALRt1xers)。 – RedGrittyBrick