如何在Python中使用zeep在SOAP请求中传递“Any”类型参数

问题描述 投票:0回答:1

我有一个 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()
抛出异常结束。

有什么想法我哪里出错了吗?

python xml soap wsdl zeep
1个回答
0
投票

我找不到以任何有意义的方式使用 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)```
© www.soinside.com 2019 - 2024. All rights reserved.