<p>Hi</p>
<p>I've used <a href="https://github.com/fiorix/wsdl2go" rel="nofollow">wsdl2go</a> in order to generate the go code from the wsdl file.</p>
<p>But since i'm still quite n00b with go i don't really understand my issue.
Here it is:</p>
<p>xml: name "station" in tag of main.GetStations.Station conflicts with name "Station" in *main.Station.XMLName</p>
<p>And the error occurs when encoding the xml
if err := encoder.Encode(envelope); err != nil {
return err
}</p>
<p>Thank you in advance!</p>
<p>This is the code generated by the wsdl2go tool:</p>
<p>package main</p>
<p>import (
"bytes"
"crypto/tls"
"encoding/xml"
"io/ioutil"
"log"
"net"
"net/http"
"time"
)</p>
<p>// against "unused imports"
var _ time.Time
var _ xml.Name</p>
<p>type WsivPortType struct {
client *SOAPClient
}</p>
<p>type SOAPClient struct {
url string
tls bool
//auth *BasicAuth
}</p>
<p>type SOAPEnvelope struct {
XMLName xml.Name <code>xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"</code></p>
<pre><code>Body SOAPBody
</code></pre>
<p>}</p>
<p>type SOAPHeader struct {
XMLName xml.Name <code>xml:"http://schemas.xmlsoap.org/soap/envelope/ Header"</code></p>
<pre><code>Header interface{}
</code></pre>
<p>}</p>
<p>type SOAPBody struct {
XMLName xml.Name <code>xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"</code></p>
<pre><code>Fault *SOAPFault `xml:",omitempty"`
Content interface{} `xml:",omitempty"`
</code></pre>
<p>}</p>
<p>type SOAPFault struct {
XMLName xml.Name <code>xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault"</code></p>
<pre><code>Code string `xml:"faultcode,omitempty"`
String string `xml:"faultstring,omitempty"`
Actor string `xml:"faultactor,omitempty"`
Detail string `xml:"detail,omitempty"`
</code></pre>
<p>}</p>
<p>type Direction struct {
XMLName xml.Name <code>xml:"http://wsiv.ratp.fr/xsd Direction"</code></p>
<pre><code>Line *Line `xml:"line,omitempty"`
Name string `xml:"name,omitempty"`
Sens string `xml:"sens,omitempty"`
StationsEndLine []*Station `xml:"stationsEndLine,omitempty"`
</code></pre>
<p>}</p>
<p>type Reseau struct {
XMLName xml.Name <code>xml:"http://wsiv.ratp.fr/xsd Reseau"</code></p>
<pre><code>Code string `xml:"code,omitempty"`
Id string `xml:"id,omitempty"`
Image string `xml:"image,omitempty"`
Name string `xml:"name,omitempty"`
</code></pre>
<p>}</p>
<p>type Line struct {
XMLName xml.Name <code>xml:"http://wsiv.ratp.fr/xsd Line"</code></p>
<pre><code>Code string `xml:"code,omitempty"`
CodeStif string `xml:"codeStif,omitempty"`
Id string `xml:"id,omitempty"`
Image string `xml:"image,omitempty"`
Name string `xml:"name,omitempty"`
Realm string `xml:"realm,omitempty"`
Reseau *Reseau `xml:"reseau,omitempty"`
</code></pre>
<p>}</p>
<p>type GeoPoint struct {
XMLName xml.Name <code>xml:"http://wsiv.ratp.fr/xsd GeoPoint"</code></p>
<pre><code>Id string `xml:"id,omitempty"`
Name string `xml:"name,omitempty"`
NameSuffix string `xml:"nameSuffix,omitempty"`
Type_ string `xml:"type,omitempty"`
X float64 `xml:"x,omitempty"`
Y float64 `xml:"y,omitempty"`
</code></pre>
<p>}</p>
<p>type Station struct {
XMLName xml.Name <code>xml:"http://wsiv.ratp.fr/xsd Station"</code></p>
<pre><code>Direction *Direction `xml:"direction,omitempty"`
GeoPointA *GeoPoint `xml:"geoPointA,omitempty"`
GeoPointR *GeoPoint `xml:"geoPointR,omitempty"`
Id string `xml:"id,omitempty"`
IdsNextA []string `xml:"idsNextA,omitempty"`
IdsNextR []string `xml:"idsNextR,omitempty"`
Line *Line `xml:"line,omitempty"`
Name string `xml:"name,omitempty"`
</code></pre>
<p>}</p>
<p>type GetStations struct {
XMLName xml.Name <code>xml:"http://wsiv.ratp.fr getStations"</code></p>
<pre><code>Station *Station `xml:"station,omitempty"`
Gp *GeoPoint `xml:"gp,omitempty"`
Distances []int32 `xml:"distances,omitempty"`
Limit int32 `xml:"limit,omitempty"`
SortAlpha bool `xml:"sortAlpha,omitempty"`
</code></pre>
<p>}</p>
<p>type GetStationsResponse struct {
XMLName xml.Name <code>xml:"http://wsiv.ratp.fr getStationsResponse"</code>
}</p>
<p>func (service <em>WsivPortType) GetStations(request *GetStations) (</em>GetStationsResponse, error) {
response := new(GetStationsResponse)
err := service.client.Call("urn:getStations", request, response)
if err != nil {
return nil, err
}</p>
<pre><code>return response, nil
</code></pre>
<p>}</p>
<p>func NewWsivPortType(url string, tls bool) *WsivPortType {
if url == "" {
url = ""
}
client := NewSOAPClient(url, tls)</p>
<pre><code>return &WsivPortType{
client: client,
}
</code></pre>
<p>}</p>
<p>func NewSOAPClient(url string, tls bool) *SOAPClient {
return &SOAPClient{
url: url,
tls: tls,
}
}</p>
<p>func (s *SOAPClient) Call(soapAction string, request, response interface{}) error {
envelope := SOAPEnvelope{
//Header: SoapHeader{},
}</p>
<pre><code>envelope.Body.Content = request
buffer := new(bytes.Buffer)
encoder := xml.NewEncoder(buffer)
//encoder.Indent(" ", " ")
if err := encoder.Encode(envelope); err != nil {
return err
}
if err := encoder.Flush(); err != nil {
return err
}
log.Println(buffer.String())
req, err := http.NewRequest("POST", s.url, buffer)
if err != nil {
return err
}
req.Header.Add("Content-Type", "text/xml; charset=\"utf-8\"")
if soapAction != "" {
req.Header.Add("SOAPAction", soapAction)
}
req.Header.Set("User-Agent", "gowsdl/0.1")
req.Close = true
tr := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: s.tls,
},
Dial: dialTimeout,
}
client := &http.Client{Transport: tr}
res, err := client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
rawbody, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if len(rawbody) == 0 {
log.Println("empty response")
return nil
}
log.Println(string(rawbody))
respEnvelope := new(SOAPEnvelope)
respEnvelope.Body = SOAPBody{Content: response}
err = xml.Unmarshal(rawbody, respEnvelope)
if err != nil {
return err
}
fault := respEnvelope.Body.Fault
if fault != nil {
return fault
}
return nil
</code></pre>
<p>}</p>
<p>func (f *SOAPFault) Error() string {
return f.String
}</p>
<p>var timeout = time.Duration(30 * time.Second)</p>
<p>func dialTimeout(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, timeout)
}</p>
<p>And this is the code i used to call the wcf service:</p>
<p>package main</p>
<p>import (
"fmt"
)</p>
<p>func main() {</p>
<pre><code>service := NewWsivPortType("http://opendata-tr.ratp.fr/wsiv/services/Wsiv", false)
station := new(Station)
station.Name = "carrefour pleyel"
getStation := new(GetStations)
getStation.Station = station
_, e := service.GetStations(getStation)
fmt.Println(e)
</code></pre>
<p>}</p>
<hr/>**评论:**<br/><br/>kostix: <pre><p>The XML unmarshaler implemented by <code>encoding/xml</code> looks for a special field present in a <code>struct</code> type of the value to unmarshal an XML element into, and tries to find there a special field named <code>XMLName</code>. If it's present, it defines the local name (and possibly the namespace) of the element to unmarshal.</p>
<p>In <code>go doc encoding/xml.Unmarshal</code>, we read:</p>
<blockquote>
<p>Unmarshal maps an XML element to a struct using the following rules. In the
rules, the tag of a field refers to the value associated with the key <code>xml</code>
in the struct field's tag (see the example above).</p>
<p>….</p>
<ul>
<li>If the <code>XMLName</code> field has an associated tag of the form
"name" or "namespace-URL name", the XML element must have
the given name (and, optionally, name space) or else Unmarshal
returns an error.</li>
</ul>
</blockquote>
<p>The definition</p>
<pre><code> type Station struct {
XMLName xml.Name xml:"http://wsiv.ratp.fr/xsd Station"
...
}
</code></pre>
<p>states that this type is to be used to unmarshal XML elements named <code>{http://wsiv.ratp.fr/xsd}Station</code> — notice the capital "S".</p>
<p>Now consider this type:</p>
<pre><code>type GetStations struct {
XMLName xml.Name xml:"http://wsiv.ratp.fr getStations"
Station *Station `xml:"station,omitempty"`
...
}
</code></pre>
<p>Here, the <code>xml</code> tag on the "Station" field of this type is used to explicitly tell the unmarshaler that the expected XML element to be unmarshaled into this field must have the name "station" (notice the small "s") but the field's type, <code>Station</code> also explicitly tells the unmarshaler the corresponding XML element must be named "Station" (and have the namespace!). Again, from the doc:</p>
<blockquote>
<ul>
<li>If the XML element contains a sub-element whose name matches
the prefix of a tag formatted as "a" or "a>b>c", unmarshal
will descend into the XML structure looking for elements with the
given names, and will map the innermost elements to that struct
field. A tag starting with ">" is equivalent to one starting
with the field name followed by ">".</li>
</ul>
</blockquote>
<p>What I find really strange about all this, is that each element of an XML doument is defined to be in <em>some</em> namespace; if it's not specified, it's defined to be an empty one "" (IIRC).</p>
<p>So I'd say the conflict should be not about <code>Station</code> vs <code>station</code> but rather about <code>{http://wsiv.ratp.fr/xsd}Station</code> (namespaced) vs <code>station</code> (without one).</p>
<p>I'm not sure what's at fault here—the <code>wsdl2go</code> package or the WSDL itself or Go, but you could start here.</p></pre>ferreirix: <pre><p>Thank you a lot! Will try to fix that when I get home :)</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传