Разобрать XML на структуру, содержащую слайс - PullRequest
0 голосов
/ 05 сентября 2018

Положение:

У меня есть такая структура XML:

<group id="26659127">
    <member ref="292403538"/>
    <member ref="298884289"/>
    <member ref="261728686"/>
    <info k="name" v="omega"/>
    <info k="rank" v="16"/>
</group>

Мне нужно преобразовать этот XML в эту структуру:

{
    Id: "26659127",
    Members: ["26659127", "298884289", "261728686"],
    Info: [
        {
            Key: "name",
            Value: "omega"
        },
        {
            Key: "rank",
            Value: "16"
        }
    ]
}

Проблема:

Я уже создал структуру для разбора XML:

type Group struct {
    Id      string   `xml:"id,attr"`
    Members []string `xml:" "`
    Info    []Info   `xml:"info"`
}

type Info struct {
    Key     string   `xml:"k,attr"`
    Value   string   `xml:"v,attr"`
}

Но, как вы можете видеть, я еще не определил выражение для Members. На самом деле, я попытался поместить сюда xml:"member,ref,attr" и xml:"member:ref,attr", но это не сработало.

Вопрос:

Есть ли возможность решить эту проблему? Если да, какое выражение мне следует использовать?

1 Ответ

0 голосов
/ 06 сентября 2018

К сожалению, не существует способа использовать демаршалер XML по умолчанию для достижения вашей цели, используя только теги struct field, поэтому вам придется либо:

  1. Извлечение структурного типа для поля «Участники», имеющего поле «ref» (аналогично типу «Информация»).
  2. Используйте пользовательский тип для "Member", который является строкой и реализует xml.Unmarshaler путем извлечения значения атрибута "ref" из связанного элемента XML.

Вот пример того, как вы можете реализовать стратегию # 2 выше ( Go Playground ):

type Group struct {
  Id      string      `xml:"id,attr"`
  Members []MemberRef `xml:"member"`
  Info    []Info      `xml:"info"`
}

type MemberRef string

func (m *MemberRef) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
  *m = MemberRef(start.Attr[0].Value) // Assume only the "ref" attribute exists.
  _, err := d.Token() // Consume and discard the synthetic xml.EndElement.
  return err
}

// ...
var group Group
err := xml.Unmarshal([]byte(xmlstr), &group)
if err != nil {
    panic(err)
}
fmt.Printf("%#v\n", group)
// main.Group{Id:"26659127", Members:[]main.MemberRef{"292403538", "298884289", "261728686"}, Info:...

Обратите внимание, что вы можете даже упорядочить эту структуру непосредственно в приведенном вами примере формата JSON:

bs, err := json.MarshalIndent(group, "", "  ")
if err != nil {
    panic(err)
}
fmt.Println(string(bs))
// {
//   "Id": "26659127",
//   "Members": [
//     "292403538",
//     "298884289",
//     "261728686"
//   ],
//   "Info": [
//     ...
...