2016-02-03 10 views
2

Я хочу создать structs = каждый тип команды.Как правильно разобрать xml

Команды имеют общую часть xml - CommandResult. Я создал интерфейс Command. Мне нужно SomeCommand реализует команду и может быть проанализирован как xml, также IsError должен быть реализован в CommandResult, другие функции должны быть реализованы SomeCommand.

Код:

type Command interface { 
    IsError() bool 

    Request(buf *bufio.Writer, params interface{}) error 
    ... 
} 

// Result of request 
type CommandResult struct { 
    Code int `xml:"code,attr" json:"code"` 
    Message string `xml:"msg" json:"msg"` 
} 

// this Command's func is realized by CommandResult 
func (self CommandResult) IsError() bool { 
    return true 
} 


// some command 
type SomeCommand struct { 
    CommandResult // CommandResult `xml:"response>result" json:"result"` 
} 

// this Command's func is realized by SomeCommand 
func (self SomeCommand) Request(buf *bufio.Writer, params interface{}) error { 
    return nil 
} 

// other Command's functions are realized by CommandResult too 

XML:

<epp> 
    <response> 
    <result code="1000"> 
     <msg>Command completed successfully</msg> 
    </result> 
    <trID> 
     <svTRID>asd</svTRID> 
    </trID> 
    </response> 
</epp> 

Ожидаемый результат:

a := SomeCommand 
xml.NewDecoder(reader).Decode(&a) 
// a.CommandResult.Code = 1000 
// a.CommandResult.Message = 'Command completed successfully' 

// a implements Command 

ответ

1
  1. Я думаю, что пути в вложенной структуры должен быть абсолютным, как все "родителя" структур являются частью «ребенка». Так что ваш

    type CommandResult struct { 
        Code int `xml:"code,attr" json:"code"` 
        Message string `xml:"msg" json:"msg"` 
    } 
    

    Должно быть больше, как

    type CommandResult struct { 
        Code int `xml:"response>result>code,attr" json:"code"` 
        Message string `xml:"response>result>msg" json:"msg"` 
    } 
    

    НО! Там мы сталкиваемся с ограничениями Go.

  2. Вы не можете использовать attr с цепью. Существует issue on Github, но похоже, что это не список приоритетов. Так что, если я прав понимаю кратчайшую версию CommandResult декларации будет:

    type CommandResult struct { 
        Result struct { 
         Code int `xml:"code,attr" json:"code"` 
         Message string `xml:"msg" json:"msg"` 
        } `xml:"response>result" json:"response"` 
    } 
    
  3. не проблема, но в случае, если вы решите конвертировать Command обратно в XML был бы хорошо, чтобы заявить о своих XMLName. Что-то вроде

    type CommandResult struct { 
        XMLName xml.Name `xml:"epp"` 
        Result struct { 
         Code int `xml:"code,attr" json:"code"` 
         Message string `xml:"msg" json:"msg"` 
        } `xml:"response>result" json:"response"` 
    } 
    

    Потому что без него кодера XML будет производить что-то вроде <SomeCommand><response>...</response></SomeCommand>

Обновления с полным примером

package main 

import (
    "bufio" 
    "encoding/xml" 
    "log" 
) 

type Command interface { 
    IsError() bool 

    Request(buf *bufio.Writer, params interface{}) error 
} 

// Result of request 
type CommandResult struct { 
    XMLName xml.Name `xml:"epp"` 
    Result struct { 
     Code int `xml:"code,attr" json:"code"` 
     Message string `xml:"msg" json:"msg"` 
    } `xml:"response>result" json:"response"` 
} 

// this Command's func is realized by CommandResult 
func (self CommandResult) IsError() bool { 
    return true 
} 

// some command 
type SomeCommand struct { 
    CommandResult 
} 

// this Command's func is realized by SomeCommand 
func (self SomeCommand) Request(buf *bufio.Writer, params interface{}) error { 
    return nil 
} 

type AnotherCommand struct { 
    CommandResult 
} 

func (self AnotherCommand) Request(buf *bufio.Writer, params interface{}) error { 
    return nil 
} 

func main() { 
    var c Command 

    c = SomeCommand{} 
    log.Println(c.IsError()) 

    c = AnotherCommand{} 
    log.Println(c.IsError()) 
} 
+0

спасибо за ответ. Я все знаю. Основная проблема для меня в том, что функция IsError() должна быть скопирована снова и снова для каждой структуры (SomeCommand, OtherCommand, ...) для реализации командного интерфейса в этом случае. И я не хочу этого делать. – Harlam

+1

@ Харлам Я не понимаю, что вы подразумеваете под «снова и снова». Если вы вставляете 'CommandResult' в' SomeCommand'' SomeCommand' автоматически «загубит» метод IsError. Я добавил полный пример в обновлении. –

+0

Теперь это понятно для меня. Большое спасибо за помощь. – Harlam

 Смежные вопросы

  • Нет связанных вопросов^_^