diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..7d0fb3a --- /dev/null +++ b/AUTHORS @@ -0,0 +1,11 @@ +# This is the official list of wsdl2go authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS file. +# +# Names should be added to this file as +# Name or Organization +# +# The email address is not required for organizations. +# +# Please keep the list sorted. + +Alexandre Fiori diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1233021 --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright 2016 wsdl2go authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * The names of authors or contributors may NOT be used to endorse or +promote products derived from this software without specific prior +written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index d3021a3..52b4469 100644 --- a/README.md +++ b/README.md @@ -3,26 +3,65 @@ wsdl2go is a command line tool to generate [Go](https://golang.org) code from [WSDL](https://en.wikipedia.org/wiki/Web_Services_Description_Language). -Usage: +Download: + +``` +go get github.com/fiorix/wsdl2go +``` + +### Usage + +Make sure you have gofmt under $GOROOT/bin, otherwise it'll fail. ``` wsdl2go < file.wsdl > hello.go ``` -Use -i for remote URLs. +Use -i for files or URLs, and -o to specify an output file. WSDL +files that contain import tags are only processed after these +resources are downloaded. It tries automatically but might fail +due to authentication or bad SSL certificates. You can force it +anyway. YOLO. + +Here's how to use the generated code: Let's say you generate the +Go code for the hello service, which provides an Echo method that +takes an EchoRequest and returns an EchoReply. To use it, you have +to create a SOAP client, then call the generated function Echo. -Once the code is generated, wsdl2go invokes gofmt from $GOROOT/bin/gofmt -and will fail have if you don't have it installed. +Example: + +``` +import ( + "/path/to/hello" + + "github.com/fiorix/wsdl2go/soap" +) + +func main() { + cli := &soap.Client{ + URL: "http://server", + Namespace: hello.Namespace, + } + req := &hello.EchoRequest{Data: "echo"} + reply, err := hello.Echo(cli, req) + ... +} +``` + +Only the **Document** style of SOAP is supported. If you're looking +for the RPC one, take another bite of your taco and move on. Soz. ### Status -Not fully compliant with SOAP or WSDL. Works for my needs and has been -tested with a few SOAP enterprise systems. +Works for my needs, been tested with a few SOAP enterprise systems. +Not fully compliant to WSDL or SOAP specs. -There are limitations related to XML namespaces in Go, which might impact -how this program works. Details: https://github.com/golang/go/issues/14407. +Because of some [limitations](https://github.com/golang/go/issues/14407) +of XML namespaces in Go, there's only so much one can do to make +things like SOAP work properly. Although, the code generated by wsdl2go +might be sufficient for most systems. -WSDL types supported: +Types supported: - [x] int - [x] long (int64) @@ -40,10 +79,7 @@ WSDL types supported: Date types are currently defined as strings, need to implement XML Marshaler and Unmarshaler interfaces. -The Go code generator (package wsdlgo) is capable of importing remote -parts of the WSDL via HTTP. You can configure its http.Client to support -authentication and self-signed certificates. - For simple types that have restrictions defined, such as an enumerated list of possible values, we generate the validation function using reflect -to compare values. +to compare values. This and the entire API might change anytime, +be warned. diff --git a/soap/client.go b/soap/client.go new file mode 100644 index 0000000..af553ae --- /dev/null +++ b/soap/client.go @@ -0,0 +1,101 @@ +// Package soap provides a SOAP HTTP client. +package soap + +import ( + "bytes" + "encoding/xml" + "io/ioutil" + "log" + "net/http" +) + +// A RoundTripper executes a request passing the given req as the SOAP +// envelope body. The HTTP response is then de-serialized onto the resp +// object. Returns error in case an error occurs serializing req, making +// the HTTP request, or de-serializing the response. +type RoundTripper interface { + RoundTrip(req, resp Message) error +} + +// Message is an opaque type used by the RoundTripper to carry XML +// documents for SOAP. +type Message interface{} + +// Header is an opaque type used as the SOAP Header element in requests. +type Header interface{} + +// AuthHeader is a Header to be encoded as the SOAP Header element in +// requests, to convey credentials for authentication. +type AuthHeader struct { + Namespace string `xml:"xmlns:ns,attr"` + Username string `xml:"ns:username"` + Password string `xml:"ns:password"` +} + +// Client is a SOAP client. +type Client struct { + URL string // URL of the server + Namespace string // SOAP Namespace + Envelope string // Optional SOAP Envelope + Header Header // Optional SOAP Header + ContentType string // Optional Content-Type (default text/xml) + Config *http.Client // Optional HTTP client +} + +// RoundTrip implements the RoundTripper interface. +func (c *Client) RoundTrip(in, out Message) error { + req := &Envelope{ + EnvelopeAttr: c.Envelope, + NSAttr: c.Namespace, + Header: c.Header, + Body: Body{Message: in}, + } + if req.EnvelopeAttr == "" { + req.EnvelopeAttr = "http://schemas.xmlsoap.org/soap/envelope/" + } + if req.NSAttr == "" { + req.NSAttr = c.URL + } + var b bytes.Buffer + err := xml.NewEncoder(&b).Encode(req) + if err != nil { + return err + } + ct := c.ContentType + if ct == "" { + ct = "text/xml" + } + cli := c.Config + if cli == nil { + cli = http.DefaultClient + } + resp, err := cli.Post(c.URL, ct, &b) + if err != nil { + return err + } + defer resp.Body.Close() + if false { + // to be removed + z, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + log.Printf("%s", z) + } + return xml.NewDecoder(resp.Body).Decode(out) +} + +// Envelope is a SOAP envelope. +type Envelope struct { + XMLName xml.Name `xml:"SOAP-ENV:Envelope"` + EnvelopeAttr string `xml:"xmlns:SOAP-ENV,attr"` + NSAttr string `xml:"xmlns:ns,attr"` + Header Message `xml:"SOAP-ENV:Header"` + Body Body +} + +// Body is the body of a SOAP envelope. +type Body struct { + XMLName xml.Name `xml:"SOAP-ENV:Body"` + Message Message +} diff --git a/wsdl/decoder_test.go b/wsdl/decoder_test.go index 581f441..cada510 100644 --- a/wsdl/decoder_test.go +++ b/wsdl/decoder_test.go @@ -24,20 +24,20 @@ func TestUnmarshal(t *testing.T) { for i, tc := range cases { f, err := os.Open(filepath.Join("testdata", tc.F)) if err != nil { - t.Errorf("test %d failed: %v", i, err) + t.Errorf("test %d (%q) failed: %v", i, tc.F, err) } defer f.Close() _, err = Unmarshal(f) if tc.E == nil { if err != nil { - t.Errorf("test %d failed: want %v, have %v", i, tc.E, err) + t.Errorf("test %d (%q) failed: want %v, have %v", i, tc.F, tc.E, err) } continue } want := reflect.ValueOf(tc.E).Type().Name() have := reflect.ValueOf(err).Type().Name() if want != have { - t.Errorf("test %d failed: want %q, have %q", i, want, have) + t.Errorf("test %d (%q) failed: want %q, have %q", i, tc.F, want, have) } } } diff --git a/wsdl/testdata/golden1.wsdl b/wsdl/testdata/golden1.wsdl index c83d04c..6fdfca9 100644 --- a/wsdl/testdata/golden1.wsdl +++ b/wsdl/testdata/golden1.wsdl @@ -1,17 +1,39 @@ - + + + + + - + - + - - + + diff --git a/wsdl/types.go b/wsdl/types.go index 938cf83..e645dd7 100644 --- a/wsdl/types.go +++ b/wsdl/types.go @@ -9,6 +9,8 @@ type Definitions struct { XMLName xml.Name `xml:"definitions"` Name string `xml:"name,attr"` TargetNamespace string `xml:"targetNamespace,attr"` + SOAPEnv string `xml:"SOAP-ENV,attr"` + SOAPEnc string `xml:"SOAP-ENC,attr"` Service Service `xml:"service"` Imports []*Import `xml:"import"` Schema Schema `xml:"types>schema"` @@ -39,14 +41,11 @@ type Address struct { // Schema of WSDL document. type Schema struct { - XMLName xml.Name `xml:"schema"` - TargetNamespace string `xml:"targetNamespace,attr"` - ElementFormDefault string `xml:"elementFormDefault,attr"` - AttributeFormDefault string `xml:"attributeFormDefault,attr"` - Imports []*ImportSchema `xml:"import"` - SimpleTypes []*SimpleType `xml:"simpleType"` - ComplexTypes []*ComplexType `xml:"complexType"` - Elements []*Element `xml:"element"` + XMLName xml.Name `xml:"schema"` + Imports []*ImportSchema `xml:"import"` + SimpleTypes []*SimpleType `xml:"simpleType"` + ComplexTypes []*ComplexType `xml:"complexType"` + Elements []*Element `xml:"element"` } // SimpleType describes a simple type, such as string. diff --git a/wsdlgo/encoder.go b/wsdlgo/encoder.go index 8485fcc..53790fd 100644 --- a/wsdlgo/encoder.go +++ b/wsdlgo/encoder.go @@ -17,6 +17,7 @@ import ( "sort" "strconv" "strings" + "text/template" "github.com/fiorix/wsdl2go/wsdl" ) @@ -42,6 +43,7 @@ type goEncoder struct { // types cache stypes map[string]*wsdl.SimpleType ctypes map[string]*wsdl.ComplexType + rtypes map[string]string // renamed ctypes old->new // funcs cache funcs map[string]*wsdl.Operation @@ -49,23 +51,31 @@ type goEncoder struct { // messages cache messages map[string]*wsdl.Message + // soap operations cache + soapOps map[string]*wsdl.BindingOperation + // whether to add supporting types - needsReflect bool needsDateType bool needsTimeType bool needsDateTimeType bool needsDurationType bool + needsNSTag map[string]string + needsPkg map[string]bool } // NewEncoder creates and initializes an Encoder that generates code to w. func NewEncoder(w io.Writer) Encoder { return &goEncoder{ - w: w, - http: http.DefaultClient, - stypes: make(map[string]*wsdl.SimpleType), - ctypes: make(map[string]*wsdl.ComplexType), - funcs: make(map[string]*wsdl.Operation), - messages: make(map[string]*wsdl.Message), + w: w, + http: http.DefaultClient, + stypes: make(map[string]*wsdl.SimpleType), + ctypes: make(map[string]*wsdl.ComplexType), + rtypes: make(map[string]string), + funcs: make(map[string]*wsdl.Operation), + messages: make(map[string]*wsdl.Message), + soapOps: make(map[string]*wsdl.BindingOperation), + needsNSTag: make(map[string]string), + needsPkg: make(map[string]bool), } } @@ -115,6 +125,7 @@ func (ge *goEncoder) encode(w io.Writer, d *wsdl.Definitions) error { ge.cacheTypes(d) ge.cacheFuncs(d) ge.cacheMessages(d) + ge.cacheSOAPOperations(d) pkg := strings.ToLower(d.Binding.Name) if pkg == "" { pkg = "internal" @@ -128,11 +139,15 @@ func (ge *goEncoder) encode(w io.Writer, d *wsdl.Definitions) error { if err != nil { return err } - fmt.Fprintf(w, "package %s\n\nimport (\n\"errors\"\n", pkg) - if ge.needsReflect { - fmt.Fprintf(w, "\"reflect\"\n") + fmt.Fprintf(w, "package %s\n\nimport (\n", pkg) + for pkg := range ge.needsPkg { + fmt.Fprintf(w, "%q\n", pkg) + } + fmt.Fprintf(w, ")\n\n") + if d.TargetNamespace != "" { + ge.writeComments(w, "Namespace", "") + fmt.Fprintf(w, "var Namespace = %q\n\n", d.TargetNamespace) } - fmt.Fprintf(w, "\n\"golang.org/x/net/context\"\n)\n\n") _, err = io.Copy(w, &b) return err } @@ -213,6 +228,12 @@ func (ge *goEncoder) cacheMessages(d *wsdl.Definitions) { } } +func (ge *goEncoder) cacheSOAPOperations(d *wsdl.Definitions) { + for _, v := range d.Binding.Operations { + ge.soapOps[v.Name] = v + } +} + // writeGoFuncs writes Go function definitions from WSDL types to w. // Functions are written in the same order of the WSDL document. func (ge *goEncoder) writeGoFuncs(w io.Writer, d *wsdl.Definitions) error { @@ -245,30 +266,90 @@ func (ge *goEncoder) writeGoFuncs(w io.Writer, d *wsdl.Definitions) error { ret[i] = ge.wsdl2goDefault(parts[1]) } } - ge.fixParamConflicts(in, out) - fmt.Fprintf(w, "func %s(%s) (%s) {\nreturn %s\n}\n\n", - strings.Title(op.Name), - strings.Join(in, ","), - strings.Join(out, ","), - strings.Join(ret, ","), - ) + ok := ge.writeSOAPFunc(w, op, in, out, ret) + if !ok { + ge.needsPkg["errors"] = true + ge.needsPkg["golang.org/x/net/context"] = true + in = append([]string{"ctx context.Context"}, in...) + ge.fixParamConflicts(in, out) + fmt.Fprintf(w, "func %s(%s) (%s) {\nreturn %s\n}\n\n", + strings.Title(op.Name), + strings.Join(in, ","), + strings.Join(out, ","), + strings.Join(ret, ","), + ) + } } return nil } +var soapFuncT = template.Must(template.New("soapFunc"). + Parse(`func {{.Name}}(cli soap.RoundTripper, {{.Input}}) ({{.Output}}) { + γ := struct { + XMLName xml.Name ` + "`xml:\"Envelope\"`" + ` + Body struct { + M {{.OutputType}} ` + "`xml:\"{{.OutputType}}\"`" + ` + } + }{} + if err = cli.RoundTrip(α, &γ); err != nil { + return {{.RetDef}}, err + } + return {{if .RetPtr}}&{{end}}γ.Body.M, nil +} +`)) + +func (ge *goEncoder) writeSOAPFunc(w io.Writer, op *wsdl.Operation, in, out, ret []string) bool { + if _, exists := ge.soapOps[op.Name]; !exists { + return false + } + if len(in) != 1 && len(out) != 2 { + return false + } + ge.needsPkg["encoding/xml"] = true + ge.needsPkg["github.com/fiorix/wsdl2go/soap"] = true + in[0] = renameParam(in[0], "α") + out[0] = renameParam(out[0], "β") + typ := strings.SplitN(out[0], " ", 2) + soapFuncT.Execute(w, &struct { + Name string + Input string + Output string + OutputType string + RetPtr bool + RetDef string + }{ + strings.Title(op.Name), + strings.Join(in, ","), + strings.Join(out, ","), + strings.TrimPrefix(typ[1], "*"), + typ[1][0] == '*', + ret[0], + }) + return true +} + +func renameParam(p, name string) string { + v := strings.SplitN(p, " ", 2) + if len(v) != 2 { + return p + } + return name + " " + v[1] +} + +// returns list of function input parameters. func (ge *goEncoder) inputParams(op *wsdl.Operation) ([]string, error) { - in := []string{"ctx context.Context"} if op.Input == nil { - return in, nil + return []string{}, nil } im := ge.trimns(op.Input.Message) req, ok := ge.messages[im] if !ok { return nil, fmt.Errorf("operation %q wants input message %q but it's not defined", op.Name, im) } - return append(in, ge.genParams(req, "Request")...), nil + return ge.genParams(req, "Request"), nil } +// returns list of function output parameters plus error. func (ge *goEncoder) outputParams(op *wsdl.Operation) ([]string, error) { out := []string{"err error"} if op.Output == nil { @@ -352,15 +433,27 @@ func (ge *goEncoder) wsdl2goType(t, suffix string) string { ge.needsDurationType = true return "Duration" default: - if suffix != "" && !strings.HasSuffix(t, suffix) { - ge.renameType(t, t+suffix) - t = v + suffix + if newname, exists := ge.rtypes[t]; exists { + t = newname + } else if suffix != "" { + // These types are parameters to functions. Since + // they are structs, we set their names to have + // suffixes Request and Response based on how + // they're used. + if strings.HasSuffix(t, suffix) { + t = v + } else { + ge.renameType(t, t+suffix) + t = v + suffix + } + // Request types need a special xml tag to enable + // encoding them correct. Responses cannot have it. + if suffix == "Request" { + ge.needsNSTag[t] = v + } } else { t = v } - if len(t) == 0 { - return "FIXME" - } return "*" + strings.Title(t) } } @@ -402,6 +495,7 @@ func (ge *goEncoder) renameType(old, name string) { if !exists { return } + ge.rtypes[old] = name name = ge.trimns(name) } ct.Name = name @@ -421,7 +515,7 @@ func (ge *goEncoder) writeGoTypes(w io.Writer, d *wsdl.Definitions) error { continue } ge.writeComments(&b, st.Name, "") - fmt.Fprintf(w, "type %s %s\n\n", st.Name, ge.wsdl2goType(st.Restriction.Base, "")) + fmt.Fprintf(&b, "type %s %s\n\n", st.Name, ge.wsdl2goType(st.Restriction.Base, "")) ge.genValidator(&b, st.Name, st.Restriction) } var err error @@ -495,6 +589,20 @@ func (ge *goEncoder) genDateTypes(w io.Writer) { } } +var validatorT = template.Must(template.New("validator").Parse(` +// Validate validates {{.TypeName}}. +func (v {{.TypeName}}) Validate() bool { + for _, vv := range []{{.Type}} { + {{range .Args}}{{.}},{{end}} + }{ + if reflect.DeepEqual(v, vv) { + return true + } + } + return false +} +`)) + func (ge *goEncoder) genValidator(w io.Writer, typeName string, r *wsdl.Restriction) { if len(r.Enum) == 0 { return @@ -508,14 +616,16 @@ func (ge *goEncoder) genValidator(w io.Writer, typeName string, r *wsdl.Restrict args[i] = v.Value } } - fmt.Fprintf(w, "// Validate validates the %s.", typeName) - fmt.Fprintf(w, "\nfunc (v %s) Validate() bool {\n", typeName) - fmt.Fprintf(w, "for _, vv := range []%s{\n", t) - fmt.Fprintf(w, "%s,\n", strings.Join(args, ",\n")) - fmt.Fprintf(w, "}{\nif reflect.DeepEqual(v, vv) { return true }\n}\nreturn false\n}\n\n") - if !ge.needsReflect { - ge.needsReflect = true - } + ge.needsPkg["reflect"] = true + validatorT.Execute(w, &struct { + TypeName string + Type string + Args []string + }{ + typeName, + t, + args, + }) } func (ge *goEncoder) genGoStruct(w io.Writer, ct *wsdl.ComplexType) error { @@ -540,6 +650,9 @@ func (ge *goEncoder) genGoStruct(w io.Writer, ct *wsdl.ComplexType) error { } ge.writeComments(w, ct.Name, ct.Doc) fmt.Fprintf(w, "type %s struct {\n", ct.Name) + if tag, exists := ge.needsNSTag[ct.Name]; exists { + fmt.Fprintf(w, "XMLName xml.Name `xml:\"ns:%s\"`\n", tag) + } err := ge.genStructFields(w, ct) if err != nil { return err @@ -600,20 +713,26 @@ func (ge *goEncoder) genElements(w io.Writer, ct *wsdl.ComplexType) error { } func (ge *goEncoder) genElementField(w io.Writer, el *wsdl.Element) { + var slicetype string if el.Type == "" && el.ComplexType != nil { seq := el.ComplexType.Sequence if seq != nil && len(seq.Elements) == 1 { n := el.Name el = el.ComplexType.Sequence.Elements[0] + slicetype = el.Name el.Name = n } } + tag := el.Name fmt.Fprintf(w, "%s ", strings.Title(el.Name)) if el.Max != "" && el.Max != "1" { fmt.Fprintf(w, "[]") + if slicetype != "" { + tag = el.Name + ">" + slicetype + } } - fmt.Fprint(w, ge.wsdl2goType(el.Type, "")) - fmt.Fprintf(w, " `xml:\"%s", el.Name) + typ := ge.wsdl2goType(el.Type, "") + fmt.Fprintf(w, "%s `xml:\"%s", typ, tag) if el.Nillable || el.Min == 0 { fmt.Fprintf(w, ",omitempty") } diff --git a/wsdlgo/testdata/importer-root.wsdl b/wsdlgo/testdata/importer-root.wsdl index d2c8407..c441514 100644 --- a/wsdlgo/testdata/importer-root.wsdl +++ b/wsdlgo/testdata/importer-root.wsdl @@ -22,11 +22,11 @@ - + - + diff --git a/wsdlgo/testdata/importer.wsdl b/wsdlgo/testdata/importer.wsdl index dc5537a..1011693 100644 --- a/wsdlgo/testdata/importer.wsdl +++ b/wsdlgo/testdata/importer.wsdl @@ -1,5 +1,3 @@ - - + + + + + + + + + + diff --git a/wsdlgo/testdata/memcache.golden b/wsdlgo/testdata/memcache.golden index a6db8f1..1fa01cd 100644 --- a/wsdlgo/testdata/memcache.golden +++ b/wsdlgo/testdata/memcache.golden @@ -1,24 +1,53 @@ package memoryservice import ( - "errors" - - "golang.org/x/net/context" + "encoding/xml" + "github.com/fiorix/wsdl2go/soap" ) +// Namespace was auto-generated from WSDL. +var Namespace = "http://localhost:8080/EchoService.wsdl" + // Get was auto-generated from WSDL. -func Get(ctx context.Context, key string) (resp *GetResponse, err error) { - return &GetResponse{}, errors.New("not implemented") +func Get(cli soap.RoundTripper, α string) (β *GetResponse, err error) { + γ := struct { + XMLName xml.Name `xml:"Envelope"` + Body struct { + M GetResponse `xml:"GetResponse"` + } + }{} + if err = cli.RoundTrip(α, &γ); err != nil { + return &GetResponse{}, err + } + return &γ.Body.M, nil } // Set was auto-generated from WSDL. -func Set(ctx context.Context, info *SetRequest) (ok bool, err error) { - return false, errors.New("not implemented") +func Set(cli soap.RoundTripper, α *SetRequest) (β bool, err error) { + γ := struct { + XMLName xml.Name `xml:"Envelope"` + Body struct { + M bool `xml:"bool"` + } + }{} + if err = cli.RoundTrip(α, &γ); err != nil { + return false, err + } + return γ.Body.M, nil } // GetMulti was auto-generated from WSDL. -func GetMulti(ctx context.Context, keys *GetMultiRequest) (values *GetMultiResponse, err error) { - return &GetMultiResponse{}, errors.New("not implemented") +func GetMulti(cli soap.RoundTripper, α *GetMultiRequest) (β *GetMultiResponse, err error) { + γ := struct { + XMLName xml.Name `xml:"Envelope"` + Body struct { + M GetMultiResponse `xml:"GetMultiResponse"` + } + }{} + if err = cli.RoundTrip(α, &γ); err != nil { + return &GetMultiResponse{}, err + } + return &γ.Body.M, nil } // Duration in WSDL format. @@ -26,7 +55,8 @@ type Duration string // GetMultiRequest was auto-generated from WSDL. type GetMultiRequest struct { - Keys []string `xml:"Keys"` + XMLName xml.Name `xml:"ns:GetMultiRequest"` + Keys []string `xml:"Keys"` } // GetMultiResponse was auto-generated from WSDL. @@ -42,6 +72,7 @@ type GetResponse struct { // SetRequest carries a key-value pair. type SetRequest struct { + XMLName xml.Name `xml:"ns:SetRequest"` Key string `xml:"Key"` Value string `xml:"Value"` Expiration Duration `xml:"Expiration,omitempty"` diff --git a/wsdlgo/testdata/memcache.wsdl b/wsdlgo/testdata/memcache.wsdl index da83010..fce92ae 100644 --- a/wsdlgo/testdata/memcache.wsdl +++ b/wsdlgo/testdata/memcache.wsdl @@ -1,4 +1,4 @@ - + - + - + @@ -103,6 +103,22 @@ + + + + + + + + + + diff --git a/wsdlgo/testdata/w3cexample1.golden b/wsdlgo/testdata/w3cexample1.golden index 096f08a..fa50816 100644 --- a/wsdlgo/testdata/w3cexample1.golden +++ b/wsdlgo/testdata/w3cexample1.golden @@ -2,7 +2,6 @@ package internal import ( "errors" - "golang.org/x/net/context" ) diff --git a/wsdlgo/testdata/w3cexample2.golden b/wsdlgo/testdata/w3cexample2.golden index 3bc4db7..d5e1917 100644 --- a/wsdlgo/testdata/w3cexample2.golden +++ b/wsdlgo/testdata/w3cexample2.golden @@ -2,7 +2,6 @@ package internal import ( "errors" - "golang.org/x/net/context" ) diff --git a/wsdlgo/testdata/w3example1.golden b/wsdlgo/testdata/w3example1.golden index 56246dd..a0208e5 100644 --- a/wsdlgo/testdata/w3example1.golden +++ b/wsdlgo/testdata/w3example1.golden @@ -1,14 +1,25 @@ package endorsementsearchsoapbinding import ( - "errors" - - "golang.org/x/net/context" + "encoding/xml" + "github.com/fiorix/wsdl2go/soap" ) +// Namespace was auto-generated from WSDL. +var Namespace = "http://namespaces.snowboard-info.com" + // GetEndorsingBoarder was auto-generated from WSDL. -func GetEndorsingBoarder(ctx context.Context, body *GetEndorsingBoarderRequest) (respBody *GetEndorsingBoarderResponse, err error) { - return &GetEndorsingBoarderResponse{}, errors.New("not implemented") +func GetEndorsingBoarder(cli soap.RoundTripper, α *GetEndorsingBoarderRequest) (β *GetEndorsingBoarderResponse, err error) { + γ := struct { + XMLName xml.Name `xml:"Envelope"` + Body struct { + M GetEndorsingBoarderResponse `xml:"GetEndorsingBoarderResponse"` + } + }{} + if err = cli.RoundTrip(α, &γ); err != nil { + return &GetEndorsingBoarderResponse{}, err + } + return &γ.Body.M, nil } // GetEndorsingBoarderFault was auto-generated from WSDL. @@ -18,8 +29,9 @@ type GetEndorsingBoarderFault struct { // GetEndorsingBoarderRequest was auto-generated from WSDL. type GetEndorsingBoarderRequest struct { - Manufacturer string `xml:"manufacturer,omitempty"` - Model string `xml:"model,omitempty"` + XMLName xml.Name `xml:"ns:GetEndorsingBoarder"` + Manufacturer string `xml:"manufacturer,omitempty"` + Model string `xml:"model,omitempty"` } // GetEndorsingBoarderResponse was auto-generated from WSDL. diff --git a/wsdlgo/testdata/w3example2.golden b/wsdlgo/testdata/w3example2.golden index 565b840..f3325a6 100644 --- a/wsdlgo/testdata/w3example2.golden +++ b/wsdlgo/testdata/w3example2.golden @@ -1,19 +1,31 @@ package stockquotesoapbinding import ( - "errors" - - "golang.org/x/net/context" + "encoding/xml" + "github.com/fiorix/wsdl2go/soap" ) +// Namespace was auto-generated from WSDL. +var Namespace = "http://example.com/stockquote.wsdl" + // GetLastTradePrice was auto-generated from WSDL. -func GetLastTradePrice(ctx context.Context, body *TradePriceRequest) (respBody *TradePriceResponse, err error) { - return &TradePriceResponse{}, errors.New("not implemented") +func GetLastTradePrice(cli soap.RoundTripper, α *TradePriceRequest) (β *TradePriceResponse, err error) { + γ := struct { + XMLName xml.Name `xml:"Envelope"` + Body struct { + M TradePriceResponse `xml:"TradePriceResponse"` + } + }{} + if err = cli.RoundTrip(α, &γ); err != nil { + return &TradePriceResponse{}, err + } + return &γ.Body.M, nil } // TradePriceRequest was auto-generated from WSDL. type TradePriceRequest struct { - TickerSymbol string `xml:"tickerSymbol,omitempty"` + XMLName xml.Name `xml:"ns:TradePriceRequest"` + TickerSymbol string `xml:"tickerSymbol,omitempty"` } // TradePriceResponse was auto-generated from WSDL.