src.dualinventive.com/go/cp3000-interface/vendor/github.com/tiaguinho/gosoap/encode.go

219 lines
3.8 KiB
Go

package gosoap
import (
"encoding/xml"
"fmt"
"reflect"
)
var tokens []xml.Token
// MarshalXML envelope the body and encode to xml
func (c Client) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
tokens = []xml.Token{}
//start envelope
if c.Definitions == nil {
return fmt.Errorf("definitions is nil")
}
startEnvelope()
if len(c.HeaderParams) > 0 {
startHeader(c.HeaderName, c.Definitions.Types[0].XsdSchema[0].TargetNamespace)
recursiveEncode(c.HeaderParams)
endHeader(c.HeaderName)
}
err := startBody(c.Method, c.Definitions.Types[0].XsdSchema[0].TargetNamespace)
if err != nil {
return err
}
recursiveEncode(c.Params)
//end envelope
endBody(c.Method)
endEnvelope()
for _, t := range tokens {
err := e.EncodeToken(t)
if err != nil {
return err
}
}
return e.Flush()
}
func recursiveEncode(hm interface{}) {
v := reflect.ValueOf(hm)
var param Param
var ok bool
switch v.Kind() {
case reflect.Map:
for _, key := range v.MapKeys() {
t := xml.StartElement{
Name: xml.Name{
Space: "",
Local: key.String(),
},
}
tokens = append(tokens, t)
recursiveEncode(v.MapIndex(key).Interface())
tokens = append(tokens, xml.EndElement{Name: t.Name})
}
case reflect.Slice:
for i := 0; i < v.Len(); i++ {
recursiveEncode(v.Index(i).Interface())
}
case reflect.String:
content := xml.CharData(v.String())
tokens = append(tokens, content)
case reflect.Struct:
param, ok = v.Interface().(Param)
if !ok {
break
}
t := xml.StartElement{
Name: xml.Name{
Space: "",
Local: param.Key,
},
}
tokens = append(tokens, t)
recursiveEncode(param.Value)
tokens = append(tokens, xml.EndElement{Name: t.Name})
}
}
func startEnvelope() {
e := xml.StartElement{
Name: xml.Name{
Space: "",
Local: "soap:Envelope",
},
Attr: []xml.Attr{
{Name: xml.Name{Space: "", Local: "xmlns:xsi"}, Value: "http://www.w3.org/2001/XMLSchema-instance"},
{Name: xml.Name{Space: "", Local: "xmlns:xsd"}, Value: "http://www.w3.org/2001/XMLSchema"},
{Name: xml.Name{Space: "", Local: "xmlns:soap"}, Value: "http://schemas.xmlsoap.org/soap/envelope/"},
{Name: xml.Name{Space: "", Local: "soap:encodingStyle"}, Value: "http://www.w3.org/2003/05/soap-encoding"},
},
}
tokens = append(tokens, e)
}
func endEnvelope() {
e := xml.EndElement{
Name: xml.Name{
Space: "",
Local: "soap:Envelope",
},
}
tokens = append(tokens, e)
}
func startHeader(m, n string) {
h := xml.StartElement{
Name: xml.Name{
Space: "",
Local: "soap:Header",
},
}
if m == "" || n == "" {
tokens = append(tokens, h)
return
}
r := xml.StartElement{
Name: xml.Name{
Space: "",
Local: m,
},
Attr: []xml.Attr{
{Name: xml.Name{Space: "", Local: "xmlns:m"}, Value: n},
},
}
tokens = append(tokens, h, r)
return
}
func endHeader(m string) {
h := xml.EndElement{
Name: xml.Name{
Space: "",
Local: "soap:Header",
},
}
if m == "" {
tokens = append(tokens, h)
return
}
r := xml.EndElement{
Name: xml.Name{
Space: "",
Local: m,
},
}
tokens = append(tokens, r, h)
}
// startToken initiate body of the envelope
func startBody(m, n string) error {
b := xml.StartElement{
Name: xml.Name{
Space: "",
Local: "soap:Body",
},
}
if m == "" || n == "" {
return fmt.Errorf("method or namespace is empty")
}
r := xml.StartElement{
Name: xml.Name{
Space: "",
Local: fmt.Sprintf("%s:%s", "m", m),
},
Attr: []xml.Attr{
{Name: xml.Name{Space: "", Local: "xmlns:m"}, Value: n},
},
}
tokens = append(tokens, b, r)
return nil
}
// endToken close body of the envelope
func endBody(m string) {
b := xml.EndElement{
Name: xml.Name{
Space: "",
Local: "soap:Body",
},
}
r := xml.EndElement{
Name: xml.Name{
Space: "",
Local: fmt.Sprintf("%s:%s", "m", m),
},
}
tokens = append(tokens, r, b)
}