原文链接: http://www.kylin-ux.com/2017/04/21/network-web-web-service系列之实例之使用urllib发送SOAP-POST请求

完整代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import urllib.request
url_jaxws = "http://localhost:9000/WS/HelloWorld"
url_spyne = "http://localhost:8000/"
data_jaxws = '''<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Body>
<ns0:helloWorld xmlns:ns0="http://webservice.kylinux.com/">
<arg0>Kylin</arg0>
<arg0>Shu</arg0>
</ns0:helloWorld>
</soap-env:Body>
</soap-env:Envelope>
'''
data_spyne = '''<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Body>
<ns0:say_hello_plus2 xmlns:ns0="spyne.examples.hello.soap">
<ns0:name_plus>
<ns0:string>Kylin</ns0:string>
<ns0:string>Shu</ns0:string>
</ns0:name_plus>
</ns0:say_hello_plus2>
</soap-env:Body>
</soap-env:Envelope>
'''
headers = {'Content-Type': 'text/xml'}
req = urllib.request.Request(url_jaxws, data=data_jaxws.encode('utf-8'), headers=headers)
res = urllib.request.urlopen(req)
print(res.read().decode('utf-8'))
req = urllib.request.Request(url_spyne, data=data_spyne.encode('utf-8'), headers=headers)
res = urllib.request.urlopen(req)
print(res.read().decode('utf-8'))

headers = {'Content-Type': 'text/xml'}
headers = {}
Unsupported Content-Type: application/x-www-form-urlencoded
headers = {'Content-Type': 'application/soap+xml; charset=utf-8'}
Unsupported Content-Type: application/soap+xml; charset=utf-8

另外
The processing instruction target matching “[xX][mM][lL]” is not allowed
是因为content can't start with a space

输出结果:
1
2
3
4
➜ websvr python3 ./invoke_ws.py
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:helloWorldResponse xmlns:ns2="http://webservice.kylinux.com/"><return>Hello world from KylinShu</return></ns2:helloWorldResponse></S:Body></S:Envelope>
<?xml version='1.0' encoding='UTF-8'?>
<soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="spyne.examples.hello.soap"><soap11env:Body><tns:say_hello_plus2Response><tns:say_hello_plus2Result><tns:string>Kylin</tns:string><tns:string>Shu</tns:string></tns:say_hello_plus2Result></tns:say_hello_plus2Response></soap11env:Body></soap11env:Envelope>
问题:

那么, data_jaxwsdata_spyne中的名字空间参数名的值从哪里取呢?

  • 名字空间
    名字空间的值取自wsdl(如http://localhost:8000/?wsdl)的<definitions><wsdl:definitions>节点中xmlns:tnstargetNamespace的值
    如,

    1
    2
    xmlns:tns="spyne.examples.hello.soap"
    targetNamespace="spyne.examples.hello.soap"
  • 参数
    参数名取自wsdl的<wsdl:types>节点
    如,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <wsdl:types>
    <xs:schema targetNamespace="spyne.examples.hello.soap" elementFormDefault="qualified">
    <xs:complexType name="stringArray">
    <xs:sequence>
    <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
    </xs:sequence>
    </xs:complexType>
    ... ...
    </xs:schema>
    </wsdl:types>