我正在使用suds
python库编写SOAP客户端。我正在使用的服务不提供WSDL文件,所以我必须手动编写一个。我正在尝试发出一个请求,它接受可变数量的类型作为参数。
目前,我对WSDL中的方法有以下内容:
<wsdl:message name="get_usertagRequest">
<wsdl:part name="email" type="xsd:string"
minOccurs="1" maxOccurs="1"/>
<wsdl:part name="tag" type="xsd:string"
minOccurs="0" maxOccurs="unbounded"/>
</wsdl:message>
我可以使用单个标记参数使用以下代码调用它:
client = Client(url)
service = client.service['debian.org']
foo = service.get_usertag('someone@debian.org', tag='malloc')
这会产生如下所示的请求:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns3="urn:Debbugs/SOAP" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns4="urn:Debbugs/SOAP/TYPES" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Header/>
<ns0:Body>
<ns3:get_usertag>
<email xsi:type="ns1:string">someone@debian.org</email>
<tag xsi:type="ns4:string">malloc</tag>
</ns3:get_usertag>
</ns0:Body>
</SOAP-ENV:Envelope>
如何修改我的代码或WSDL以生成如下所示的请求?
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns3="urn:Debbugs/SOAP" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns4="urn:Debbugs/SOAP/TYPES" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Header/>
<ns0:Body>
<ns3:get_usertag>
<email xsi:type="ns1:string">someone@debian.org</email>
<tag xsi:type="ns4:string">malloc</tag>
<tag xsi:type="ns4:string">anothertag</tag>
</ns3:get_usertag>
</ns0:Body>
</SOAP-ENV:Envelope>
更新了尝试次数
我根据herry的答案尝试了新的方法。将他的建议直接插入wsdl
会导致无法解析wsdl:
<xsd:schema targetNamespace="ns6:your_namespace" attributeFormDefault="qualified" elementFormDefault="qualified">
<xsd:element name="tag_list">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="tag" nillable="true" type="ns4:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Suds抛出异常:Exception: prefix (ns6) not resolved
我尝试将element
和complexType
定义添加到我现有的类型名称空间:
<wsdl:types>
<schema targetNamespace="urn:Debbugs/SOAP/TYPES"
xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<element name="tag_list">
<complexType>
<sequence>
<element maxOccurs="unbounded" minOccurs="0" name="tag" nillable="true" type="xsd:string" />
</sequence>
</complexType>
</element>
- 剪断 -
<wsdl:message name="get_usertagRequest">
<wsdl:part name="email" type="xsd:string"
minOccurs="1" maxOccurs="1"/>
<wsdl:part name="tag" element="types:tag_list"
minOccurs="0" maxOccurs="unbounded"/>
这导致了以下请求:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns3="urn:Debbugs/SOAP" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns4="urn:Debbugs/SOAP/TYPES" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Header/>
<ns0:Body>
<ns3:get_usertag>
<email xsi:type="ns1:string">someone@debian.org</email>
<tag_list xsi:type="ns4:tag_list">malloc</tag_list>
</ns3:get_usertag>
</ns0:Body>
</SOAP-ENV:Envelope>
由于它更改了类型,因此从服务器返回了错误:
suds.WebFault: Server raised fault: 'Application failed during request deserialization: Unrecognized type '{urn:Debbugs/SOAP/TYPES}tag_list'
即使没有错误,我也无法让suds
两次发送相同的标签。使用更新的wsdl
:
# only malloc is sent in the request
foo = service.get_usertag('someone@debian.org', 'malloc', 'foo')
# results in suds.TypeNotFound: Type not found: 'tag_list'
foo = service.get_usertag('someone@debian.org', ['malloc', 'foo'])
我目前正在使用的完整wsdl可以找到here。
答案 0 :(得分:0)
根据您的评论我已经开始调查服务器端为什么不处理数组。我已经检查了SOAP.pm中的代码。我只专注于get_usertag方法,它处理或将处理一个或三个参数:
my %ut = get_usertag('don@donarmstrong.com','this-bug-sucks','eat-this-bug');
my %ut = get_usertag('don@donarmstrong.com');
我认为您的目标是发出一个请求,该请求接受可变数量的类型作为参数。以前,我提议你在参数中使用一个复合类型(complexType),它有很多或零参数。
现在我查看它所说的SOAP::Lite documentation:
- 不支持多维,部分传输和稀疏阵列(但支持阵列阵列,以及任何其他阵列 数据结构,您可以添加自己的实现 SOAP ::数据)。
- 对WSDL架构的有限支持。
因此,支持简单数组和SOAP :: Data。从技术上讲,它可以发送和处理数组(第二个限制对我来说是可怕的消息)。但我可以想象另一个原因(另一个客户端使用此方法...)不支持数组。另请查看differences between a SOAP::WSDL and SOAP::Lite。
我在考虑如何发送许多参数的许多选项,但是每个选项都需要更改服务器端代码。也许你可以做一些hacks / magic来解决这个问题(使用一个包含所有参数并在服务器端拆分的参数),但我认为简单的SOAP::Data是更好的选择。
我没有改变WSDL结构。你可以使用我的波纹管代码。请在get_usertag方法中更改服务器端代码(之前我没有看到perl代码,我无法编写此代码)。该方法声明了两个字段$email
和@tags
。请更改为$email
和$tag_list
。 $tag_list
包含@tags
数组。
基于您的WSDL,我创建了简单的WSDL。它只包含两个操作,消息和只有一个模式。这个shema使用你的命名空间。所以它不需要指定另一个名称空间。这是WSDL的相关部分:
<wsdl:types>
<xsd:schema targetNamespace="urn:Debbugs/SOAP" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:element name="get_usertagResponse" >
<xsd:complexType>
<xsd:sequence>
<xsd:element name="msg" minOccurs="0" maxOccurs="unbounded" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<!--The new Tag_lis element-->
<xsd:element name="Tag_list" >
<xsd:complexType>
<xsd:sequence>
<xsd:element name="tag" minOccurs="0" maxOccurs="unbounded" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<!--get_usertagRequest use Tag_lis element-->
<wsdl:message name="get_usertagRequest">
<wsdl:part name="email" type="xsd:string"/>
<wsdl:part name="tag_list" element="tns:Tag_list"/>
</wsdl:message>
<wsdl:message name="get_usertagResponse">
<wsdl:part name="msg" type="tns:get_usertagResponse"/>
</wsdl:message>
我认为你可以将这部分实现给你的WSDL。如果可能,请合并架构。这段代码有效,我在soapUi中测试过。我收到以下请求:
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="urn:Debbugs/SOAP">
<soapenv:Header/>
<soapenv:Body>
<soap:get_usertag soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<email xsi:type="xsd:string">?</email>
<soap:Tag_list>
<!--Zero or more repetitions:-->
<tag xsi:type="xsd:string">?</tag>
</soap:Tag_list>
</soap:get_usertag>
</soapenv:Body>
</soapenv:Envelope>
在这种情况下,客户端发送以下参数:
client = Client(url)
service = client.service['debian.org']
foo = service.get_usertag('someone@debian.org', tag_list=['malloc', 'amother'])
答案 1 :(得分:0)
client = Client(url)
//forming request
arrayoftagList = client.factory.create('ArrayOfString')
arrayoftagList.tag_list = [malloc,anothertag]
print client.service.get_usertag(someone@debian.org, arrayoftagList).string
<强>编辑:强>
根据您当前的wsdl解决方案:
根据你的wsdl,你的tagRequest是,
<wsdl:message name="get_usertagRequest">
<wsdl:part name="email" type="xsd:string"
minOccurs="1" maxOccurs="1"/>
<!-- <wsdl:part name="tag" type="xsd:string" -->
<!-- minOccurs="0" maxOccurs="unbounded"/> -->
<wsdl:part name="tag_list" type="types:ArrayOfString"
minOccurs="0" maxOccurs="unbounded"/>
现在,如果您将转到类型:ArrayOfString,
<complexType name="ArrayOfString">
<sequence>
<element minOccurs="0" maxOccurs="unbounded"
name="string" nillable="true"
type="xsd:string"/>
</sequence>
</complexType>
所以你会像这样形成你的请求,
client = Client(url)
//forming request
arrayoftagList = client.factory.create('ArrayOfString')
arrayoftagList.string = [malloc,anothertag]
print client.service.get_usertag(someone@debian.org, arrayoftagList).string
这将生成这样的消息(我已经排除了命名空间,这不完全正确)
<get_usertag>
<email>someone@debian.org</email>
<string>malloc</string>
<string>anothertag</string>
</get_usertag>
现在如果你想在上面的请求中将字符串替换为“tag”,请在wsdl中更改,
<complexType name="ArrayOfString">
<sequence>
<element minOccurs="0" maxOccurs="unbounded"
name="tag" nillable="true"
type="xsd:string"/>
</sequence>
</complexType>
<强>更新强>
编辑你的wsdl解决方案:
这里我只更新了你的wsdl for get_Usertag操作,你可以按照这种方法相应地设计你的wsdl。保存以下wsdl并生成请求。
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
name="Debbugs/SOAP"
targetNamespace="urn:Debbugs/SOAP"
xmlns:tns="urn:Debbugs/SOAP"
xmlns:types="urn:Debbugs/SOAP/TYPES"
xmlns:apachens="http://xml.apache.org/xml-soap"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<wsdl:types>
<schema targetNamespace="urn:Debbugs/SOAP/TYPES"
xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<element name="UsertagRequest">
<complexType>
<sequence>
<element name="email" type="xsd:string"
minOccurs="1" MaxOccurs="1"/>
<element name="tag" type="xsd:string"
minOccurs="0" MaxOccurs="unbounded"/>
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
<wsdl:message name="get_usertagRequest">
<wsdl:part name = "parameters" element="types:UsertagRequest"/>
</wsdl:message>
<wsdl:message name="get_usertagResponse">
<wsdl:part name="s-gensym3" type="xsd:string"/>
</wsdl:message>
<wsdl:portType name="Debbugs/SOAP">
<wsdl:operation name="get_usertag">
<wsdl:input message="tns:get_usertagRequest">
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:Debbugs/SOAP"
use="encoded"/>
</wsdl:input>
<wsdl:output message="tns:get_usertagResponse">
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:Debbugs/SOAP"
use="encoded"/>
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Debbugs/SOAP/BINDING" type="tns:Debbugs/SOAP">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="get_usertag">
<wsdl:input message="tns:get_usertagRequest">
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:Debbugs/SOAP"
use="encoded"/>
</wsdl:input>
<wsdl:output message="tns:get_usertagResponse">
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:Debbugs/SOAP"
use="encoded"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="Debbugs/SOAP/SERVICE">
<wsdl:port binding="tns:Debbugs/SOAP/BINDING" name="gnu.org">
<wsdlsoap:address location="http://debbugs.gnu.org/cgi/soap.cgi"/>
</wsdl:port>
<wsdl:port binding="tns:Debbugs/SOAP/BINDING" name="debian.org">
<wsdlsoap:address location="http://bugs.debian.org/cgi-bin/soap.cgi"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
如果您将使用上面的wsdl并生成soap请求消息,它将是,
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="urn:Debbugs/SOAP" xmlns:typ="urn:Debbugs/SOAP/TYPES">
<soapenv:Header/>
<soapenv:Body>
<soap:get_usertag soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<typ:UsertagRequest>
<email xsi:type="xsd:string">?</email>
<!--Optional:-->
<tag xsi:type="xsd:string">?</tag>
</typ:UsertagRequest>
</soap:get_usertag>
</soapenv:Body>
</soapenv:Envelope>