// UnmarshalXML implement xml.Unmarshaler func (b *Body) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { if b.Content == nil { return xml.UnmarshalError("Content must be a pointer to a struct") } var ( token xml.Token err error consumed bool ) Loop: for { if token, err = d.Token(); err != nil { return err } if token == nil { break } switch se := token.(type) { case xml.StartElement: if consumed { return xml.UnmarshalError("Found multiple elements inside SOAP body; not wrapped-document/literal WS-I compliant") } else if se.Name.Space == "http://schemas.xmlsoap.org/soap/envelope/" && se.Name.Local == "Fault" { b.Fault = &Fault{} b.Content = nil err = d.DecodeElement(b.Fault, &se) if err != nil { return err } consumed = true } else { b.SOAPBodyContentType = se.Name.Local if err = d.DecodeElement(b.Content, &se); err != nil { return err } consumed = true } case xml.EndElement: break Loop } } return nil }
// UnmarshalElement handles the unmarshalling of the details // according to the specified types information. func UnmarshalElement(details []byte, typesInfo interface{}) ([]interface{}, error) { if typesInfo == nil { return nil, ErrMissingTypesInfo } mt, mtOK := typesInfo.(map[string]reflect.Type) mp, mpOK := typesInfo.(map[string]interface{}) usingPtr := reflect.TypeOf(typesInfo).Kind() == reflect.Ptr usingMT := mtOK && len(mt) > 0 usingMP := mpOK && len(mp) > 0 // Checking if the type information was passed // using one of the three supported approaches. if !(usingPtr || usingMP || usingMT) { return nil, ErrMissingTypesInfo } var results []interface{} dec := xml.NewDecoder(bytes.NewReader(details)) for { // Get the next token to be processed. tok, err := dec.Token() if err != nil { if err == io.EOF { return results, nil } return nil, err } if tok == nil { return results, nil } switch se := tok.(type) { case xml.StartElement: if usingPtr { if err := dec.DecodeElement(typesInfo, &se); err != nil { return nil, err } results = append(results, typesInfo) continue } if usingMP { if ptr, ok := mp[se.Name.Local]; ok { if reflect.TypeOf(ptr).Kind() != reflect.Ptr { return nil, xml.UnmarshalError("non-pointer passed to unmarshal element " + se.Name.Local) } if err := dec.DecodeElement(ptr, &se); err != nil { return nil, err } results = append(results, ptr) } continue } if usingMT { if typ, ok := mt[se.Name.Local]; ok { ptr := reflect.New(typ).Interface() if err := dec.DecodeElement(ptr, &se); err != nil { return nil, err } results = append(results, ptr) } continue } } } }
package xml import ( "bytes" "encoding/xml" "io" "reflect" ) // Errors that can be thrown. var ( ErrMissingTypesInfo = xml.UnmarshalError("The type information has not been specified.") ) // UnmarshalElement handles the unmarshalling of the details // according to the specified types information. func UnmarshalElement(details []byte, typesInfo interface{}) ([]interface{}, error) { if typesInfo == nil { return nil, ErrMissingTypesInfo } mt, mtOK := typesInfo.(map[string]reflect.Type) mp, mpOK := typesInfo.(map[string]interface{}) usingPtr := reflect.TypeOf(typesInfo).Kind() == reflect.Ptr usingMT := mtOK && len(mt) > 0 usingMP := mpOK && len(mp) > 0 // Checking if the type information was passed // using one of the three supported approaches. if !(usingPtr || usingMP || usingMT) {