Giter Site home page Giter Site logo

xmlutil's Introduction

xmlutil

https://stackoverflow.com/questions/11767642/wsdl-soap-support-on-go

There isn't support for WSDL in Go. Support in other languages are either static or dynamic: Either structs are pre-generated from the WSDL, or it's done on the fly with hash tables.

You can, however, encode and decode SOAP requests manually. I found that the standard encoding/xml package to be insufficient for SOAP. There are so many quirks in different servers, and the limitations in encoding/xml make it difficult generate a request these servers are happy with.

For example, some servers need xsi:type="xsd:string" on every string tag. In order to do this properly your struct needs to look like this for encoding/xml:

type MethodCall struct { One XSI Two XSI }

type XSI struct { Type string xml:"xsi:type,attr" Vaue string xml:",chardata" } And you construct it like this:

MethodCall{ XSI{"xsd:string", "One"}, XSI{"xsd:string", "Two"}, } Which gives you:

One Two Now this might be ok. It certainly gets the job done. But what if you needed more than just a string? encoding/xml currently doesn't support interface{}.

As you can see this gets complicated. If you had one SOAP API to integrate, this probably wouldn't be too bad. What if you had several, each with their own quirks?

Wouldn't it be nice if you could just do this?

type MethodCall struct { One string Two string } Then say to encoding/xml: "This server want xsi types".

To solve this problem I created github.com/webconnex/xmlutil. It's a work in progress. It doesn't have all the features of encoding/xml's encoder/decoder, but it has what is needed for SOAP.

Here's a working example:

package main

import ( "bytes" "encoding/xml" "fmt" "github.com/webconnex/xmlutil" "log" //"net/http" )

type Envelope struct { Body xml:"soap:" }

type Body struct { Msg interface{} }

type MethodCall struct { One string Two string }

type MethodCallResponse struct { Three string }

func main() { x := xmlutil.NewXmlUtil() x.RegisterNamespace("http://www.w3.org/2001/XMLSchema-instance", "xsi") x.RegisterNamespace("http://www.w3.org/2001/XMLSchema", "xsd") x.RegisterNamespace("http://www.w3.org/2003/05/soap-envelope", "soap") x.RegisterTypeMore(Envelope{}, xml.Name{"http://www.w3.org/2003/05/soap-envelope", ""}, []xml.Attr{ xml.Attr{xml.Name{"xmlns", "xsi"}, "http://www.w3.org/2001/XMLSchema-instance"}, xml.Attr{xml.Name{"xmlns", "xsd"}, "http://www.w3.org/2001/XMLSchema"}, xml.Attr{xml.Name{"xmlns", "soap"}, "http://www.w3.org/2003/05/soap-envelope"}, }) x.RegisterTypeMore("", xml.Name{}, []xml.Attr{ xml.Attr{xml.Name{"http://www.w3.org/2001/XMLSchema-instance", "type"}, "xsd:string"}, })

buf := new(bytes.Buffer)
buf.WriteString(`<?xml version="1.0" encoding="utf-8"?>`)
buf.WriteByte('\n')
enc := x.NewEncoder(buf)
env := &Envelope{Body{MethodCall{
    One: "one",
    Two: "two",
}}}
if err := enc.Encode(env); err != nil {
    log.Fatal(err)
}
// Print request
bs := buf.Bytes()
bs = bytes.Replace(bs, []byte{'>', '<'}, []byte{'>', '\n', '<'}, -1)
fmt.Printf("%s\n\n", bs)

/*
    // Send response, SOAP 1.2, fill in url, namespace, and action
    var r *http.Response
    if r, err = http.Post(url, "application/soap+xml; charset=utf-8; action="+namespace+"/"+action, buf); err != nil {
        return
    }
    dec := x.NewDecoder(r.Body)
*/
// Decode response
dec := x.NewDecoder(bytes.NewBufferString(`<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
    <soap:Body>
        <MethodCallResponse>
            <Three>three</Three>
        </MethodCallResponse>
    </soap:Body>
</soap:Envelope>`))
find := []xml.Name{
    xml.Name{"", "MethodCallResponse"},
    xml.Name{"http://www.w3.org/2003/05/soap-envelope", "Fault"},
}
var start *xml.StartElement
var err error
if start, err = dec.Find(find); err != nil {
    log.Fatal(err)
}
if start.Name.Local == "Fault" {
    log.Fatal("Fault!") // Here you can decode a Soap Fault
}
var resp MethodCallResponse
if err := dec.DecodeElement(&resp, start); err != nil {
    log.Fatal(err)
}
fmt.Printf("%#v\n\n", resp)

} With the above example I use the Find method to get the response object, or a Fault. This isn't strictly necessary. You can also do it like this:

x.RegisterType(MethodCallResponse{}) ... // Decode response dec := x.NewDecoder(bytes.NewBufferString(<?xml version="1.0" encoding="utf-8"?> <soap:Envelope> <soap:Body> <MethodCallResponse> <Three>three</Three> </MethodCallResponse> </soap:Body> </soap:Envelope>)) var start *xml.StartElement var resp Envelope if err := dec.DecodeElement(&resp, start); err != nil { log.Fatal(err) } fmt.Printf("%#v\n\n", resp) You'll find the Find method useful when your data looks like this:

soap:Envelope soap:Body diffgr:diffgram three </diffgr:diffgram> </soap:Body> </soap:Envelope> This is a DiffGram, part of Microsoft .NET. You can use the Find method to get to Table1. The Decode and DecodeElement method also works on slices. So you can pass in a []MethodCallResponse if NewDataSet happens to contain more than one result.

I do agree with Zippower that SOAP does suck. But unfortunately a lot of enterprises use SOAP, and you're sometimes forced to use these APIs. With the xmlutil package I hope to make it a little less painful to work with.

xmlutil's People

Contributors

lukescott avatar windhooked avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.