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

How to pass "Any" type parameter in SOAP request using zeep in Python

提问人:mroshaw 提问时间:9/28/2023 更新时间:10/4/2023 访问量:75

问:

我有一个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_typeget_element**paramsparamsclient.service.ExecuteQuery()

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

python xml soap wsdl zeep

评论

0赞 Paul-ET 9/28/2023
不清楚你要求什么?
0赞 mroshaw 9/28/2023
我认为很清楚:我已经发布了 Any 类型的 WSDL。我已经发布了我想使用 zeep 从 WSDL 生成的 XML。我已经发布了我认为可以实现这一目标的代码,但事实并非如此。我已经发布了代码生成的错误。还需要什么信息才能使我的问题更清楚?

答:

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)