219 lines
3.8 KiB
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)
|
|
}
|