issue consuming wsdl

xuanbao · · 821 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hi</p> <p>I&#39;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&#39;m still quite n00b with go i don&#39;t really understand my issue. Here it is:</p> <p>xml: name &#34;station&#34; in tag of main.GetStations.Station conflicts with name &#34;Station&#34; 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 ( &#34;bytes&#34; &#34;crypto/tls&#34; &#34;encoding/xml&#34; &#34;io/ioutil&#34; &#34;log&#34; &#34;net&#34; &#34;net/http&#34; &#34;time&#34; )</p> <p>// against &#34;unused imports&#34; 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:&#34;http://schemas.xmlsoap.org/soap/envelope/ Envelope&#34;</code></p> <pre><code>Body SOAPBody </code></pre> <p>}</p> <p>type SOAPHeader struct { XMLName xml.Name <code>xml:&#34;http://schemas.xmlsoap.org/soap/envelope/ Header&#34;</code></p> <pre><code>Header interface{} </code></pre> <p>}</p> <p>type SOAPBody struct { XMLName xml.Name <code>xml:&#34;http://schemas.xmlsoap.org/soap/envelope/ Body&#34;</code></p> <pre><code>Fault *SOAPFault `xml:&#34;,omitempty&#34;` Content interface{} `xml:&#34;,omitempty&#34;` </code></pre> <p>}</p> <p>type SOAPFault struct { XMLName xml.Name <code>xml:&#34;http://schemas.xmlsoap.org/soap/envelope/ Fault&#34;</code></p> <pre><code>Code string `xml:&#34;faultcode,omitempty&#34;` String string `xml:&#34;faultstring,omitempty&#34;` Actor string `xml:&#34;faultactor,omitempty&#34;` Detail string `xml:&#34;detail,omitempty&#34;` </code></pre> <p>}</p> <p>type Direction struct { XMLName xml.Name <code>xml:&#34;http://wsiv.ratp.fr/xsd Direction&#34;</code></p> <pre><code>Line *Line `xml:&#34;line,omitempty&#34;` Name string `xml:&#34;name,omitempty&#34;` Sens string `xml:&#34;sens,omitempty&#34;` StationsEndLine []*Station `xml:&#34;stationsEndLine,omitempty&#34;` </code></pre> <p>}</p> <p>type Reseau struct { XMLName xml.Name <code>xml:&#34;http://wsiv.ratp.fr/xsd Reseau&#34;</code></p> <pre><code>Code string `xml:&#34;code,omitempty&#34;` Id string `xml:&#34;id,omitempty&#34;` Image string `xml:&#34;image,omitempty&#34;` Name string `xml:&#34;name,omitempty&#34;` </code></pre> <p>}</p> <p>type Line struct { XMLName xml.Name <code>xml:&#34;http://wsiv.ratp.fr/xsd Line&#34;</code></p> <pre><code>Code string `xml:&#34;code,omitempty&#34;` CodeStif string `xml:&#34;codeStif,omitempty&#34;` Id string `xml:&#34;id,omitempty&#34;` Image string `xml:&#34;image,omitempty&#34;` Name string `xml:&#34;name,omitempty&#34;` Realm string `xml:&#34;realm,omitempty&#34;` Reseau *Reseau `xml:&#34;reseau,omitempty&#34;` </code></pre> <p>}</p> <p>type GeoPoint struct { XMLName xml.Name <code>xml:&#34;http://wsiv.ratp.fr/xsd GeoPoint&#34;</code></p> <pre><code>Id string `xml:&#34;id,omitempty&#34;` Name string `xml:&#34;name,omitempty&#34;` NameSuffix string `xml:&#34;nameSuffix,omitempty&#34;` Type_ string `xml:&#34;type,omitempty&#34;` X float64 `xml:&#34;x,omitempty&#34;` Y float64 `xml:&#34;y,omitempty&#34;` </code></pre> <p>}</p> <p>type Station struct { XMLName xml.Name <code>xml:&#34;http://wsiv.ratp.fr/xsd Station&#34;</code></p> <pre><code>Direction *Direction `xml:&#34;direction,omitempty&#34;` GeoPointA *GeoPoint `xml:&#34;geoPointA,omitempty&#34;` GeoPointR *GeoPoint `xml:&#34;geoPointR,omitempty&#34;` Id string `xml:&#34;id,omitempty&#34;` IdsNextA []string `xml:&#34;idsNextA,omitempty&#34;` IdsNextR []string `xml:&#34;idsNextR,omitempty&#34;` Line *Line `xml:&#34;line,omitempty&#34;` Name string `xml:&#34;name,omitempty&#34;` </code></pre> <p>}</p> <p>type GetStations struct { XMLName xml.Name <code>xml:&#34;http://wsiv.ratp.fr getStations&#34;</code></p> <pre><code>Station *Station `xml:&#34;station,omitempty&#34;` Gp *GeoPoint `xml:&#34;gp,omitempty&#34;` Distances []int32 `xml:&#34;distances,omitempty&#34;` Limit int32 `xml:&#34;limit,omitempty&#34;` SortAlpha bool `xml:&#34;sortAlpha,omitempty&#34;` </code></pre> <p>}</p> <p>type GetStationsResponse struct { XMLName xml.Name <code>xml:&#34;http://wsiv.ratp.fr getStationsResponse&#34;</code> }</p> <p>func (service <em>WsivPortType) GetStations(request *GetStations) (</em>GetStationsResponse, error) { response := new(GetStationsResponse) err := service.client.Call(&#34;urn:getStations&#34;, 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 == &#34;&#34; { url = &#34;&#34; } client := NewSOAPClient(url, tls)</p> <pre><code>return &amp;WsivPortType{ client: client, } </code></pre> <p>}</p> <p>func NewSOAPClient(url string, tls bool) *SOAPClient { return &amp;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(&#34; &#34;, &#34; &#34;) 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(&#34;POST&#34;, s.url, buffer) if err != nil { return err } req.Header.Add(&#34;Content-Type&#34;, &#34;text/xml; charset=\&#34;utf-8\&#34;&#34;) if soapAction != &#34;&#34; { req.Header.Add(&#34;SOAPAction&#34;, soapAction) } req.Header.Set(&#34;User-Agent&#34;, &#34;gowsdl/0.1&#34;) req.Close = true tr := &amp;http.Transport{ TLSClientConfig: &amp;tls.Config{ InsecureSkipVerify: s.tls, }, Dial: dialTimeout, } client := &amp;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(&#34;empty response&#34;) 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 ( &#34;fmt&#34; )</p> <p>func main() {</p> <pre><code>service := NewWsivPortType(&#34;http://opendata-tr.ratp.fr/wsiv/services/Wsiv&#34;, false) station := new(Station) station.Name = &#34;carrefour pleyel&#34; 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&#39;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&#39;s tag (see the example above).</p> <p>….</p> <ul> <li>If the <code>XMLName</code> field has an associated tag of the form &#34;name&#34; or &#34;namespace-URL name&#34;, 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:&#34;http://wsiv.ratp.fr/xsd Station&#34; ... } </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 &#34;S&#34;.</p> <p>Now consider this type:</p> <pre><code>type GetStations struct { XMLName xml.Name xml:&#34;http://wsiv.ratp.fr getStations&#34; Station *Station `xml:&#34;station,omitempty&#34;` ... } </code></pre> <p>Here, the <code>xml</code> tag on the &#34;Station&#34; 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 &#34;station&#34; (notice the small &#34;s&#34;) but the field&#39;s type, <code>Station</code> also explicitly tells the unmarshaler the corresponding XML element must be named &#34;Station&#34; (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 &#34;a&#34; or &#34;a&gt;b&gt;c&#34;, 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 &#34;&gt;&#34; is equivalent to one starting with the field name followed by &#34;&gt;&#34;.</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&#39;s not specified, it&#39;s defined to be an empty one &#34;&#34; (IIRC).</p> <p>So I&#39;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&#39;m not sure what&#39;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

821 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传