Skip to content

Instantly share code, notes, and snippets.

@michaeljs1990
Created February 20, 2015 17:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michaeljs1990/540fdd00aace78a44093 to your computer and use it in GitHub Desktop.
Save michaeljs1990/540fdd00aace78a44093 to your computer and use it in GitHub Desktop.
xml parser
package parsing
import (
"encoding/xml"
"io"
"log"
"reflect"
"code.google.com/p/go-charset/charset"
_ "code.google.com/p/go-charset/data" //
)
// StreamXML holds the chan that you will
// need to read your xml from.
type StreamXML struct {
Stream chan interface{}
Element string
}
// NewStreamXML returns a new StreamXML
// struct that will parse on tokens matching
// the passed in element and makes a stream
// of type x. Paincs on wront input types.
func NewStreamXML(element string) *StreamXML {
return &StreamXML{
Stream: make(chan interface{}),
Element: element,
}
}
// StreamingDecode takes an io.Reader and marshals the
// value into a given structure
func (s *StreamXML) StreamingDecode(r io.Reader, x interface{}) {
if reflect.TypeOf(x).Elem().Kind() != reflect.Struct &&
reflect.TypeOf(x).Kind() == reflect.Ptr {
panic("StreamingDecode expects a ptr to a struct for the second param")
}
decoder := xml.NewDecoder(r)
decoder.CharsetReader = charset.NewReader
for {
t, err := decoder.Token()
// This code is really just checking if
// err is signaling to us that we have
// hit the end of the file with io.EOF
if err != nil {
close(s.Stream)
break
}
switch e := t.(type) {
case xml.StartElement:
// Look for tokens that are the same as the passed in
// elem string and decode them into a struct
if e.Name.Local == s.Element {
err = decoder.DecodeElement(reflect.ValueOf(x).Interface(), &e)
if err != nil {
log.Printf("%s", err.Error())
}
// send it down stream
s.Stream <- x
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment