我正在使用 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 .
最佳答案
根据您的评论,我已经开始调查服务器端不处理数组的原因。我已经检查了您的 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它说:
- No support for multidimensional, partially transmitted and sparse arrays (however arrays of arrays are supported, as well as any other data structures, and you can add your own implementation with SOAP::Data).
- Limited support for WSDL schema.
因此,支持简单数组和 SOAP::Data。从技术上讲,可以发送和处理数组(第二个限制对我来说是个坏消息)。但我可以想象不支持数组的另一个原因(另一个客户端使用这种方法......)。请同时检查 differences between a SOAP::WSDL and SOAP::Lite .
我想过很多选项如何发送很多参数,但是对于每个选项都需要更改服务器端代码。也许你可以做一些 hack/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'])
关于python - 使用 suds 在 SOAP 请求中多次发送相同类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21071589/