我有一个 WSDL,它在所有 SOAP 操作中使用“any”类型作为核心元素 (Element)。请注意,我已将其修剪掉,因为它很大:
<?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()
抛出异常结束。
有什么想法我哪里出错了吗?
我找不到以任何有意义的方式使用 AnyObject 的答案。
但是,我确实通过使用
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)```