提问人:mroshaw 提问时间:9/28/2023 更新时间:10/4/2023 访问量:75
如何在 Python 中使用 zeep 在 SOAP 请求中传递“Any”类型参数
How to pass "Any" type parameter in SOAP request using zeep in Python
问:
我有一个WSDL,它在所有SOAP操作中对核心元素(Element)使用“any”类型。请注意,我已经将其修剪掉了,因为它非常大:
<?xml version="1.0" encoding="utf-8"?>
<definitions targetNamespace="urn:xtk:queryDef" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="urn:xtk:queryDef" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema elementFormDefault="qualified" targetNamespace="urn:xtk:queryDef">
<s:complexType name="Element">
<s:sequence>
<s:any processContents="lax"/>
</s:sequence>
</s:complexType>
<s:element name="ExecuteQuery">
<s:complexType>
<s:sequence>
<s:element maxOccurs="1" minOccurs="1" name="sessiontoken" type="s:string" />
<s:element maxOccurs="1" minOccurs="1" name="entity" type="tns:Element" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="ExecuteQueryResponse">
<s:complexType>
<s:sequence>
<s:element maxOccurs="1" minOccurs="1" name="pdomOutput" type="tns:Element" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</types>
<message name="ExecuteQueryIn">
<part element="tns:ExecuteQuery" name="parameters" />
</message>
<message name="ExecuteQueryOut">
<part element="tns:ExecuteQueryResponse" name="parameters" />
</message>
<portType name="queryDefMethodsSoap">
<operation name="ExecuteQuery">
<input message="tns:ExecuteQueryIn" />
<output message="tns:ExecuteQueryOut" />
</operation>
</portType>
<binding name="queryDefMethodsSoap" type="tns:queryDefMethodsSoap">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="ExecuteQuery">
<soap:operation soapAction="xtk:queryDef#ExecuteQuery" style="document" />
<input>
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal" />
</input>
<output>
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal" />
</output>
</operation>
</binding>
<service name="XtkQueryDef">
<port binding="tns:queryDefMethodsSoap" name="queryDefMethodsSoap">
<soap:address location="https://xxxxxxxxxxxxxx/nl/jsp/soaprouter.jsp" />
</port>
</service>
</definitions>
我想在 Python 3 中使用生成此有效负载:zeep
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:xtk:queryDef">
<soapenv:Header/>
<soapenv:Body>
<urn:ExecuteQuery>
<urn:sessiontoken>xxxxxxx</urn:sessiontoken>
<urn:entity>
<queryDef schema="nms:recipient" operation="select">
<select>
<node expr="@email"/>
<node expr="@lastName+'-'+@firstName"/>
<node expr="Year(@birthDate)"/>
</select>
<orderBy>
<node expr="@birthDate" sortDesc="true"/>
</orderBy>
</queryDef>
</urn:entity>
</urn:ExecuteQuery>
</soapenv:Body>
</soapenv:Envelope>
但是我一辈子都无法弄清楚如何管理 WSDL 中的“Any”类型:
<s:complexType name="Element">
<s:sequence>
<s:any processContents="lax"/>
</s:sequence>
</s:complexType>
这是 XML 中“实体”节点所需的类型。我尝试过的所有内容都会导致 zeep 的异常。
这是我到目前为止所拥有的:
# Executes a query and returns the result set
def execute_query(session_token):
# Load the WSDL locally - not authorised to get from server
wsdl_url = os.path.abspath("querydef_dev.wsdl")
history = HistoryPlugin()
client = Client(wsdl_url, plugins=[history])
execute_query_type = client.get_element("ns0:ExecuteQuery")
entity_type = client.get_type("ns0:Element")
any_entity = xsd.AnyObject(entity_type, entity_type(_value_1={'queryDef': [{'schema': 'recipients'}]}))
params = execute_query_type(entity=any_entity, sessiontoken=session_token)
response = client.service.ExecuteQuery(params)
if __name__ == '__main__':
execute_query('xxxxxxx')
该代码专门给出了以下错误:
AttributeError: 'dict' object has no attribute 'value'. Did you mean: 'values'?
我以为我已经理解了它,用来设置事情。xsd.AnyObject
我尝试了许多与 , 的组合,并使用 和 调用服务。一切都以抛出的异常结束。get_type
get_element
**params
params
client.service.ExecuteQuery()
有什么想法我哪里出错了吗?
答:
0赞
mroshaw
10/4/2023
#1
我找不到以任何有意义的方式使用 AnyObject 的答案。
但是,我确实设法通过使用手动创建“Any”节点上下文来使其工作。lxml
因此,对于我上面描述的用例:
def execute_query(session_token):
# Load the WSDL locally - not authorised to get from server
wsdl_url = os.path.abspath("querydef_dev.wsdl")
history = HistoryPlugin()
client = Client(wsdl_url, plugins=[history])
# Construct the query def
query_def_element = etree.Element('query_def')
query_def_element.set('schema', 'nms:recipient')
query_def_element.set('operation', 'select')
select_element = etree.SubElement(query_def_element, 'select')
node_element = etree.SubElement(select_element, 'node')
node_element.set('expr', '@email')
node_element2 = etree.SubElement(select_element, 'node')
node_element2.set('expr', '"@lastName+"-""+@firstName"')
node_element3 = etree.SubElement(select_element, 'node')
node_element3.set('expr', 'Year(@birthDate)')
order_element = etree.SubElement(query_def_element, 'orderBy')
order_node_element = etree.SubElement(order_element, 'node')
order_node_element.set('expr', '"@birthDate"')
order_node_element.set('expr', 'sortDesc="true')
# Construct the final payload
data = {
"sessiontoken": session_token,
"entity": {
"_value_1": query_def_element
}
}
# Call the service
response = client.service.ExecuteQuery(**data)
评论