python在SOAP请求中产生错误的名称空间前缀
我使用python/suds来实现客户端,并且在wsdl中由element ref=
定义的参数类型的参数的发送SOAP头中出现错误的名称空间前缀。python在SOAP请求中产生错误的名称空间前缀
.wsdl正在引用数据类型.xsd文件,请参见下文。问题是功能GetRecordAttributes
及其类型gbt:recordReferences
的第一个参数。
文件:browse2.wsdl
<xsd:schema targetNamespace="http://www.grantadesign.com/10/10/Browse" xmlns="http://www.grantadesign.com/10/10/Browse" xmlns:gbt="http://www.grantadesign.com/10/10/GrantaBaseTypes" elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:import schemaLocation="grantabasetypes2.xsd" namespace="http://www.grantadesign.com/10/10/GrantaBaseTypes"/>
<xsd:element name="GetRecordAttributes">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="gbt:recordReferences">
</xsd:element>
引用的文件:grantabasetypes2.xsd用肥皂水发送
<element name="recordReferences">
<complexType>
<sequence>
<element name="record" minOccurs="0" maxOccurs="unbounded" type="gbt:MIRecordReference"/>
</sequence>
</complexType>
</element>
SOAP请求:
<SOAP-ENV:Envelope xmlns:ns0="http://www.grantadesign.com/10/10/GrantaBaseTypes" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://www.grantadesign.com/10/10/Browse" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
<ns2:GetRecordAttributes>
<ns2:recordReferences>
<ns0:record>
</ns0:record>
</ns2:recordReferences>
</ns2:GetRecordAttributes>
</ns1:Body>
</SOAP-ENV:Envelope>
问题:<ns2:recordReferences>
前缀错误,应为<ns0:recordReferences>
,因为它属于在.xsd中定义的名称空间...GrantaBaseTypes
。
这发生在wsdl中由ref=
定义的所有参数。这怎么能自动修复?
注意:我通过curl手动发送xml SOAP请求来检查服务是否接受“好”前缀。
UPDATE
我插手与SUDS源代码和下述经验修正力与ref=
属性的所有元件承担REF-ED命名空间(先前,他们采取在架构根名称空间或任何tns
是) :
文件:/suds/xsd/sxbase.py
class SchemaObject(object):
....
def namespace(self, prefix=None):
ns = self.schema.tns
#FIX BEGIN
if self.ref and self.ref in self.schema.elements.keys():
ns = self.ref
#FIX END
作品与我的服务,但我不知道这是否会破坏其他的事情秒。我宁愿选择不改变SUDS源代码的更智能的解决方案。
感谢,
亚历
写Suds plugin修改XML在发送前。
from suds.client import Client
from suds.plugin import MessagePlugin
class MyPlugin(MessagePlugin):
def marshalled(self, context):
#modify this line to reliably find the "recordReferences" element
context.envelope[1][0][0].setPrefix('ns0')
client = Client(WSDL_URL, plugins=[MyPlugin()])
报价肥皂水文档:
整理()
提供了机会,检查/发送之前修改信封文档插件。
对于这个特定的情况,这将工作正常。然而,由于在不同的树位置有很多这样的参数,所以用手修复它们并不是最佳的。我希望_prefix ns0这样的东西适用于ref = _的所有元素,并且可以有理由地解析整个xml树,我相信context.envelope不会保留'ref ='信息。 – 2012-04-20 08:06:18
另一种选择是延伸'DocumentPlugin'修改WSDL/XSD目的,'解析()'方法(参见文档)将被调用两次(一个用于WSDL,另一个用于XSD)。 – dusan 2012-04-20 17:17:05
辉煌,谢谢!有趣的是,我必须在与最初的例子完全相同的地方(结构上)更正信封。这里有模式吗? – Gesias 2013-03-15 03:16:37
你可以建立自己的SOAP消息,并使用SoapClient
发送消息:
sc = SoapClient(cli.service.XXXMethod.client,cli.service.XXXMethod.method)
sc.send(some_soap_doc)
我用肥皂水访问的BizTalk/IIS SOAP服务时,有完全相同的问题。 从我可以从时,有一个“复杂类型”是不是“目标名称”(它有它自己的),其中有一个孩子,这也是一个复杂类型的组成部分,但没有命名空间的设置它发生的WSDL告诉。在BizTalk中,这意味着孩子应该和父母一样属于同一个命名空间,但是Sud似乎认为它应该是目标命名空间的一部分......
源代码中的修复解决了“正确的”,但因为我希望能够不用每次我去另一个解决方案时应用补丁升级....
我的解决办法是跳过肥皂水和刚才复制的原始XML,用它作为模板,将值复制到它中...不是很美,但至少很简单。 在我看来,添加插件的解决方案同样是硬编码的,可能更难以维护。
我喜欢的正则表达式:)
import re
class EnvelopeFixer(MessagePlugin):
def sending(self, context):
# rimuovi i prefissi
context.envelope = re.sub('ns[0-9]:', '', context.envelope)
return context.envelope
您的方法doens't工作得很好:WebFault:服务器引发错误:'请求的根元素无法确定。 – Allen 2013-10-02 14:06:26
mmhhh ...所以插件策略是... – 2013-10-08 08:06:09
这显然是在栈中的错误; “自动”是什么意思?例如,您是否愿意与您的工具配合使用不同但同等的XSD?从你所说的话来看,如果你想用本地定义的元素替换ref,它就可以工作;对于所有XSD关心,生成的XML将是相同的。如果你考虑改变航班,比如通过代理使用某种XSLT,那将是一种不同的方法。我可以推荐一个解决方案,它会自动重构您的XSD以替换本地元素。 – 2012-04-18 16:04:56
我真的试图移动和变化的定义,但因为我不是专家,也许我coudn't找准正确的语法,泡沫不停地把错误的命名空间存在。我也不喜欢这些,因为它们是由外部供应商提供的,并且可能会发生变化。请参阅UPDATE以获取迄今为止发现的非最佳解决方案。 – 2012-04-19 09:18:41