2014-12-17 2 views
0

Я пытаюсь маршализация некоторых XML, которое структурировано как в следующем примере:Демаршаллизации XML с (XPath) условиями

<player> 
<stat type="first_name">Somebody</stat> 
<stat type="last_name">Something</stat> 
<stat type="birthday">06-12-1987</stat> 
</player> 

Он мертв легко распаковать это в структуры, как

type Player struct { 
    Stats []Stat `xml:"stat"` 
} 

но я ищу, чтобы найти способ, чтобы распаковать его в структуру, которая больше походит на

type Player struct { 
    FirstName string `xml:"stat[@Type='first_name']"` 
    LastName string `xml:"stat[@Type='last_name']"` 
    Birthday Time `xml:"stat[@Type='birthday']"` 
} 

есть ли способ d o это со стандартным кодированием/xml пакетом? Если нет, можете ли вы дать мне подсказку о том, как можно разделить такую ​​«проблему» на ходу? (в основном, лучшие практики в архитектуре программного обеспечения go для такой задачи).

спасибо!

+0

Я не думаю, что это возможно с помощью кодирования/XML. Лучшая практика в Go - написать код. Многие люди находят код написания неэлегантным, но не сложно и не странно решать проблемы программирования с помощью кода. – Volker

+1

'encoding/xml' не реализует xpath. Вы пытались найти что-нибудь такое? http://godoc.org/?q=xpath – JimB

+0

tbh, no. Но я старался как можно больше придерживаться стандартной библиотеки, потому что я совершенно новый для Go и хочу, чтобы основывались до того, как я утонул в слоях абстракции. Спасибо, что указали мне на godoc.org tho! Даже не знал, что еще один – paukul

ответ

0

Пакет encoding/xml не реализует xpath, но имеет простой набор методов выбора, которые он может использовать.

Вот пример того, как вы можете развязать XML-код с помощью encoding/xml. Поскольку статистика имеет одинаковый тип, с теми же атрибутами, самый простой способ их декодирования будет представлять собой фрагмент того же типа. http://play.golang.org/p/My10GFiWDa

var doc = []byte(`<player> 
<stat type="first_name">Somebody</stat> 
<stat type="last_name">Something</stat> 
<stat type="birthday">06-12-1987</stat> 
</player>`) 

type Player struct { 
    XMLName xml.Name  `xml:"player"` 
    Stats []PlayerStat `xml:"stat"` 
} 

type PlayerStat struct { 
    Type string `xml:"type,attr"` 
    Value string `xml:",chardata"` 
} 

И если это то, что вам нужно часто трансформировать, вы могли бы сделать преобразование с помощью метода UnamrshalXML: http://play.golang.org/p/htoOSa81Cn

type Player struct { 
    XMLName xml.Name `xml:"player"` 
    FirstName string 
    LastName string 
    Birthday string 
} 

func (p *Player) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 
    for { 
     t, err := d.Token() 
     if err == io.EOF { 
      break 
     } else if err != nil { 
      return err 
     } 

     if se, ok := t.(xml.StartElement); ok { 

      t, err = d.Token() 
      if err != nil { 
       return err 
      } 

      var val string 
      if c, ok := t.(xml.CharData); ok { 
       val = string(c) 
      } else { 
       // not char data, skip for now 
       continue 
      } 

      // assuming we have exactly one Attr 
      switch se.Attr[0].Value { 
      case "first_name": 
       p.FirstName = val 
      case "last_name": 
       p.LastName = val 
      case "birthday": 
       p.Birthday = val 
      } 
     } 
    } 
    return nil 
} 
Смежные вопросы