mvantellingen / python-zeep

A Python SOAP client
http://docs.python-zeep.org
Other
1.89k stars 586 forks source link

ComplexType not receiving Namespace for each attribute #129

Closed janos97 closed 8 years ago

janos97 commented 8 years ago

I'm working with a rather finicky WSDL that expects the namespace prefix for every attribute. (Same wsdl as previously discussed)

Could you please suggest a way to force the prefix to show up?

Tested against: 0.11.0, 0.12.0, 0.13.0, 0.14.0.dev0

Zeep produces:

<soap-env:Envelope xmlns:ns3="http://www.sample.com/schemas/public/cm/open-api/persistency/model" xmlns:ns5="http://www.sample.com/schemas/public/cm/open-api/persistency/operations" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
  <soap-env:Body>
    <ns5:GetMOsRequest>
      <ns3:configuration confId="1"/>
      <ns5:moId>SRV-324</ns5:moId>
      <ns5:moId>SRV-424</ns5:moId>
    </ns5:GetMOsRequest>
  </soap-env:Body>
</soap-env:Envelope>

but the server is expecting "ns3:confId" instead of "confId":

<soap-env:Envelope xmlns:ns3="http://www.sample.com/schemas/public/cm/open-api/persistency/model" xmlns:ns5="http://www.sample.com/schemas/public/cm/open-api/persistency/operations" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
  <soap-env:Body>
    <ns5:GetMOsRequest>
      <ns3:configuration ns3:confId="1"/>
      <ns5:moId>SRV-324</ns5:moId>
      <ns5:moId>SRV-424</ns5:moId>
    </ns5:GetMOsRequest>
  </soap-env:Body>
</soap-env:Envelope>

Edited for readability

mvantellingen commented 8 years ago

The attributeFormDefault has a default of 'unqualified'. In the wsdl I received from you earlier that wasn't overridden so it's a bit weird that the server is expected a qualified attribute.

Can you check if soapui generates the correct xml?

janos97 commented 8 years ago

SoapUI does indeed generate the correct XML.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:oper="http://www.sample.com/schemas/public/cm/open-api/persistency/operations" xmlns:mod="http://www.sample.com/schemas/public/cm/open-api/persistency/model">
   <soapenv:Header/>
   <soapenv:Body>
      <oper:GetMOsRequest>
         <mod:configuration mod:confId="?"/>
         <!--Zero or more repetitions:-->
         <oper:moId>?</oper:moId>
      </oper:GetMOsRequest>
   </soapenv:Body>
</soapenv:Envelope>
mvantellingen commented 8 years ago

Should be fixed now, thanks! Global attributes like global elements should always be qualified.

janos97 commented 8 years ago

It doesn't appear to be working. ZEEP is now serializing incorrectly. (using 0.14.0.dev0)

Specifically, it is nesting the 'ns5:moId' objects under 'ns3:configuration' instead of treating them as siblings under the 'ns5:GetMOsRequest' as expected.

<soap-env:Envelope xmlns:ns3="http://www.sample.com/schemas/public/cm/open-api/persistency/model" xmlns:ns5="http://www.sample.com/schemas/public/cm/open-api/persistency/operations" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
  <soap-env:Body>
    <ns5:GetMOsRequest>
      <ns3:configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns5:GetMOsRequest">
        <ns3:configuration ns3:confId="1"/>
        <ns5:moId>SRV-324</ns5:moId>
        <ns5:moId>SRV-424</ns5:moId>
      </ns3:configuration>
    </ns5:GetMOsRequest>
  </soap-env:Body>
</soap-env:Envelope>

Example code used to create:

from zeep import Client
from lxml import etree
client = Client('./OpenCmPersistencyService.wsdl')
configuration = client.get_element('ns3:configuration')
conf_id = configuration(confId=1)
obj = client.get_element('ns5:GetMOsRequest')
GetMOsReq = obj(configuration=configuration(confId=1), moId=['SRV-324', 'SRV-424'])
print(etree.tostring(client.service._binding.create_message('getManagedObjects', GetMOsReq), pretty_print=True))
mvantellingen commented 8 years ago

This doesn't match the signature which python -mzeep <wsdl> gives.

getManagedObjects(configuration: configuration(), moId: xsd:MOId[]) -> errorCode: xsd:token, cause: xsd:string, result: {batchItemMOResult: batchItemMOResult()}

Try this::

from zeep import Client
from lxml import etree
client = Client('./OpenCmPersistencyService.wsdl')

configuration = client.get_element('ns3:configuration')
node = client.service._binding.create_message(
    'getManagedObjects',
    configuration=configuration(confId=1),
    moId=['SRV-324', 'SRV-424'])

print(etree.tostring(node, pretty_print=True))

It should however have returned an error that invalid kwargs where passed. I'll need to look into that.

janos97 commented 8 years ago

My humblest apologies, I think someone switched the office to decaf.

It serialized perfectly when I gave it the correct input under 0.14.0.dev0, no errors encountered.

janos97 commented 8 years ago

When I attempt to parse the response from this message, the script just hangs.

Based on what I see in the debug, it is probably the kwargs you indicated, but wanted to at least ask.

Pycharm indicates: self: Unable to get repr for <class 'zeep.objects.Configuration'> args: <type 'tuple'>: () kwargs: {'confId': 1}

Using the correctly serialized request:

from zeep import Client
client = Client('./OpenCmPersistencyService.wsdl')
configuration = client.get_element('ns3:configuration')
resp = client.service.getManagedObjects(configuration=configuration(confId=1), moId=['SRV-324', 'SRV-424'])

Transaction sent:

<soap-env:Envelope xmlns:ns3="http://www.sample.com/schemas/public/cm/open-api/persistency/model" xmlns:ns5="http://www.sample.com/schemas/public/cm/open-api/persistency/operations" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
  <soap-env:Body>
    <ns5:GetMOsRequest>
      <ns3:configuration ns3:confId="1"/>
      <ns5:moId>SRV-324</ns5:moId>
      <ns5:moId>SRV-424</ns5:moId>
    </ns5:GetMOsRequest>
  </soap-env:Body>
</soap-env:Envelope>

Response received (correct response):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <GetMOsResponse xmlns:a="http://www.sample.com/schemas/public/cm/open-api/persistency/query" xmlns:b="http://www.sample.com/schemas/public/cm/open-api/persistency/metadata" xmlns:c="http://www.sample.com/schemas/public/cm/open-api/common" xmlns:d="http://www.sample.com/schemas/public/cm/open-api/persistency/model" xmlns="http://www.sample.com/schemas/public/cm/open-api/persistency/operations">
      <c:errorCode>OK</c:errorCode>
      <result>
        <batchItemMOResult>
          <c:errorCode>OK</c:errorCode>
          <d:managedObject d:metaClass="GENSRV:SRV" d:metaVersion="UBL2016" d:moId="SRV-324">
            <d:p name="name">SERVER324</d:p>
          </d:managedObject>
        </batchItemMOResult>
        <batchItemMOResult>
          <c:errorCode>OK</c:errorCode>
          <d:managedObject d:metaClass="GENSRV:SRV" d:metaVersion="UBW2016" d:moId="SRV-424">
            <d:p name="name">SERVER424</d:p>
          </d:managedObject>
        </batchItemMOResult>
      </result>
    </GetMOsResponse>
  </soapenv:Body>
</soapenv:Envelope>
mvantellingen commented 8 years ago

Ok fixed the issue in master (ce515b049d106871fb08b0ea68390d2a62b67cc0). I'll leave this open until i've added a unittest for it.

janos97 commented 8 years ago

Confirmed working in master (ce515b0).