Reputation: 3611
I have an XML document like this:
<val>
<alpha β='γ'/>
<α δ='ε'/>
(a whole bunch of the above, in random order)
</val>
in other words, a heterogeneous list. I would like to unmarshal it using the Go encoding/xml
package. How can I do this?
Upvotes: 3
Views: 340
Reputation: 417662
You can't model such XML documents in Go, and you can't unmarshal into interace{}
, so I would suggest event-driven parsing for this.
This event-driven parsing means when you are parsing (the tokens of) the XML document, you receive events like "start element encountered", or "end element encountered" (with details of the element of course), and these events control the flow of your program (branch and/or change internal state based on them).
The following example will show you the principle of this. It does not handle more complex XMLs because I wanted the example to be short, but this technique can be used to parse any XML documents.
Create an xml.Decoder
using xml.NewDecoder()
, and parse the content of the XML by calling Decoder.Token()
repeatedly (in a loop).
The elements inside <val>
will be collected in a slice of type []Entry
:
type Entry struct {
Name string
Attr string
Value string
}
func main() {
decoder := xml.NewDecoder(strings.NewReader(src))
entries := []Entry{}
for {
t, err := decoder.Token()
if err != nil {
if err != io.EOF {
fmt.Println(err)
}
break
}
if se, ok := t.(xml.StartElement); ok && len(se.Attr) > 0 {
entries = append(entries, Entry{
Name: se.Name.Local,
Attr: se.Attr[0].Name.Local,
Value: se.Attr[0].Value,
})
}
}
fmt.Printf("%+v\n", entries)
}
const src = `<val>
<alpha β='γ'/>
<α δ='ε'/>
<x y='z'/>
</val>`
Output (try it on the Go Playground):
[{Name:alpha Attr:β Value:γ} {Name:α Attr:δ Value:ε} {Name:x Attr:y Value:z}]
Upvotes: 3