Dechenjm / pysimplesoap

Automatically exported from code.google.com/p/pysimplesoap
0 stars 0 forks source link

wsdl_parse #103

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Dear Mariano,

I have called client.Soapclient(wswd=nhost) and I'm getting "Tag not found: 
types..." error message, because wsdl.types is not exist.

wsdl.types is not exist, because it is not in primary wsdl xml. It's exist an 
other uri. The wsdl definition second part is comming from <import ... /> tag, 
and wsdl_parse is not recognize it.

For example: http://...?WSDL
<?xml version="..." encoding="..." ?>
<definitions ...>
  <import namespace="..." location="http://.../Dispatcher?wsdl=1" />
  <binding>
   ...
  </binding>
  <service name="...">
  </service>
</definitions>

Is there a way, to solve my problem?

Regards,
Tibor

Original issue reported on code.google.com by dspub...@freemail.hu on 28 May 2013 at 9:13

GoogleCodeExporter commented 9 years ago
Can you download and test this:

https://github.com/rcarmo/pysimplesoap/archive/master.zip

That's an unofficial branch but seems to have some patches that could help you, 
let me know if that works and I'll take a look

Also, consider to attach some code (.py) and the wsdl so eventually we can test 
it

Original comment by reingart@gmail.com on 29 May 2013 at 6:24

GoogleCodeExporter commented 9 years ago
Hi Reingart,

The result is same with master version, than before with the official version 
too.

  File "/pysimplesoap/client.py", line 135, in __init__
    self.services = wsdl and self.wsdl_parse(wsdl, cache=cache)
  File "/pysimplesoap/client.py", line 452, in wsdl_parse
    self.namespace = dict(wsdl.types("schema", ns=xsd_uri)[:]).get 'targetNamespace', self.namespace)
  File "/pysimplesoap/simplexml.py", line 369, in __getattr__
    return self.__call__(tag)
  File "/pysimplesoap/simplexml.py", line 365, in __call__
    raise AttributeError(u"Tag not found: %s (%s)" % (tag, unicode(e)))
AttributeError: Tag not found: types (No elements found)

I'm sending an example wsdl. There's an <import > tag in wsdl. It's importing 
an other part of wsdl from defined location (as per schmas xsd).

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:tns="http://webservice/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://webservice" 
name="DispatcherServiceImplService">

<!-- IMPORTANT TAG-->
<import namespace="http://ws" 
location="http://123.123.123.123:6170/Dispatcher?wsdl=1" />
<!-- IMPORTANT TAG-->

<binding xmlns:ns1="http://ws" name="DispatcherServiceImplPortBinding" 
type="ns1:Dispatcher">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" 
/>
<operation name="getRequestStatus">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal"></soap:body>
</input>
<output>
<soap:body use="literal"></soap:body>
</output>
</operation>
</binding>
<service name="DispatcherServiceImplService">
<port name="DispatcherServiceImplPort" 
binding="tns:DispatcherServiceImplPortBinding">
<soap:address location="http://123.123.123.123:6170/Dispatcher"></soap:address>
</port>
</service>
</definitions>

I have changed clinet.py, but I think it's only temporary, compromise solution.

# Open uri and read xml:
xml1 = fetch(url)
# Parse WSDL XML:
wsdl = SimpleXMLElement(xml1, namespace=wsdl_uri)

for i in wsdl._element.getElementsByTagName('import'):
  definition_location=i.getAttribute('location');
  definition_namespace=i.getAttribute('namespace');
  if debug: print "Importing definition %s from %s" % (definition_namespace, definition_location);

  xml2=fetch(definition_location);
  doc2 = xml.dom.minidom.parseString(xml2);

  xml1=xml1.replace('</definitions>',doc2.getElementsByTagName('definitions')[0].toxml()+'</definitions>');

  wsdl = SimpleXMLElement(xml1, namespace=wsdl_uri)
  #update attributes
  for n in doc2.getElementsByTagName('definitions')[0]._attrs:
    wsdl[n]=doc2.getElementsByTagName('definitions')[0].getAttribute(n);

Original comment by dspub...@freemail.hu on 30 May 2013 at 7:23

GoogleCodeExporter commented 9 years ago
Ok, thanks for testing, we're trying to improve an merge both repositories, I 
thought the "import" issue was solved in the latest changes.

Could you attach the two wsdl so we can make a test case?

The xml can be "mangled" avoiding any sensitive ip address or method name, just 
to fully reproduce the issue and test/debug the fix.

Thanks for the patch, altough it could be temporary, modifing the xml is an 
interesting workaround.

Original comment by reingart@gmail.com on 30 May 2013 at 3:23

GoogleCodeExporter commented 9 years ago
Hi,

I'm sending the needed wsdls.

"modifing the xml is an interesting workaround" You are right, but it's a very 
quick solution, and I have no enough time to find the best one ;-)

Original comment by dspub...@freemail.hu on 1 Jun 2013 at 12:56

Attachments:

GoogleCodeExporter commented 9 years ago
Here's an another test case:

semenov@cheyenne ~ $ python -c 'import pysimplesoap; 
pysimplesoap.client.SoapClient(wsdl="https://test.paymentgate.ru/testpayment/web
services/merchant-ws?wsdl")'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pysimplesoap/client.py", line 133, in __init__
    self.services = wsdl and self.wsdl_parse(wsdl, cache=cache)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pysimplesoap/client.py", line 549, in wsdl_parse
    self.namespace = dict(wsdl.types('schema', ns=xsd_uri)[:]).get('targetNamespace', self.namespace)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pysimplesoap/simplexml.py", line 374, in __getattr__
    return self.__call__(tag)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pysimplesoap/simplexml.py", line 370, in __call__
    raise AttributeError("Tag not found: %s (%s)" % (tag, e))
AttributeError: Tag not found: types (No elements found)

semenov@cheyenne ~ $ pip freeze|grep -i soap
PySimpleSOAP==1.10

Original comment by m...@ilyasemenov.com on 28 Aug 2013 at 11:06

GoogleCodeExporter commented 9 years ago
Could you try the latest development version directly from the repository?
It includes a lot of fixes and enhancements about wsdl parsing.

You can use mercurial to download it:

hg clone https://code.google.com/p/pysimplesoap/ 

Original comment by reingart@gmail.com on 28 Aug 2013 at 1:10

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Yes, it doesn't crash on loading WSDL anymore, but it messes with the 
namespaces in the imported file. For instance, 
client.getOrderStatusExtended(order={'merchantOrderNumber':'1'}) generates this 
request:

----------------------------
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
    <getOrderStatusExtended xmlns="http://soap.merchant.api.web.phoenix.bpc.ru/">
    <order><merchantOrderNumber xmlns="http://engine.paymentgate.ru/webservices/merchant">1</merchantOrderNumber></order></getOrderStatusExtended>
</soap:Body>
</soap:Envelope>
----------------------------

The namespaces for getOrderStatusExtended and order are wrong (although the 
namespace for merchantOrderNumber is correct somehow?). Obviously, this request 
is refused by the server:
"Message part 
{http://soap.merchant.api.web.phoenix.bpc.ru/}getOrderStatusExtended was not 
recognized.  (Does it exist in service WSDL?)"

Original comment by m...@ilyasemenov.com on 28 Aug 2013 at 2:27

GoogleCodeExporter commented 9 years ago
Could you try passing a namespace prefix?

For example, when creating the client:

client = SoapClient(wsdl="...", ns="ru")

This will instruct PySimpleSoap to use namespaces explicitelly in the 
parameters.

Also, if you can attach a simple source code example I could debug it.

Original comment by reingart@gmail.com on 28 Aug 2013 at 4:02

GoogleCodeExporter commented 9 years ago
ns="ru" didn't make a difference. The XML document was restructured (xmlns= 
moved into ns: prefix), but its semantics was kept intact (and wrong).

Here's the code:

import pysimplesoap, logging
logging.basicConfig(level=logging.DEBUG)
client = 
pysimplesoap.client.SoapClient(wsdl="https://test.paymentgate.ru/testpayment/web
services/merchant-ws?wsdl")
client.getOrderStatusExtended(order={'merchantOrderNumber':'1'})

The server will reply with wsse:Security error (that's a private merchant web 
service after all), but you will see in the debug output that the generated 
SOAP body is invalid. In particular, this:

<getOrderStatusExtended xmlns="http://soap.merchant.api.web.phoenix.bpc.ru/">
<order><merchantOrderNumber 
xmlns="http://engine.paymentgate.ru/webservices/merchant">1</merchantOrderNumber
></order></getOrderStatusExtended>

should be:

<getOrderStatusExtended 
xmlns="http://engine.paymentgate.ru/webservices/merchant">
<order><merchantOrderNumber>1</merchantOrderNumber></order></getOrderStatusExten
ded>

because all these types and elements are defined by the imported WSDL 
(https://test.paymentgate.ru/testpayment/webservices/merchant-ws?wsdl=MerchantSe
rvice.wsdl) within a single namespace.

By the way, that's what suds generates for the same request:
----------------------------
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:ns0="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:ns1="http://engine.paymentgate.ru/webservices/merchant" 
xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Header/>
   <ns2:Body>
      <ns1:getOrderStatusExtended>
         <order>
            <merchantOrderNumber>1</merchantOrderNumber>
         </order>
      </ns1:getOrderStatusExtended>
   </ns2:Body>
</SOAP-ENV:Envelope>
----------------------------

Original comment by m...@ilyasemenov.com on 28 Aug 2013 at 4:31

GoogleCodeExporter commented 9 years ago
Can you test the latest revision 095994a20a98, it includes a tentative fix:

https://code.google.com/p/pysimplesoap/source/detail?r=095994a20a98a0448c3515c2a
6a792fee2d730c0

Original comment by reingart@gmail.com on 29 Aug 2013 at 6:51

GoogleCodeExporter commented 9 years ago
It's better now but still the server doesn't like the request.

Generated request:
-------------
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header><wsse:Security>...</wsse:Security></soap:Header>
<soap:Body>
    <getOrderStatusExtended xmlns="http://engine.paymentgate.ru/webservices/merchant">
    <order><merchantOrderNumber xmlns="http://engine.paymentgate.ru/webservices/merchant">1</merchantOrderNumber></order></getOrderStatusExtended>
</soap:Body>
</soap:Envelope>
-------------

Server response:
-------------
SoapFault: soap:Server: Found element 
{http://engine.paymentgate.ru/webservices/merchant}order but could not find 
matching RPC/Literal part
-------------

Unfortunately I don't know SOAP well enough to understand what causes this. I 
tried to remove xmlns= from merchantOrderNumber but this didn't make any 
difference.

Original comment by m...@ilyasemenov.com on 29 Aug 2013 at 10:28

GoogleCodeExporter commented 9 years ago
(I also tried to add xmlns= to <order> and that didn't make any difference, 
too.)

Original comment by m...@ilyasemenov.com on 29 Aug 2013 at 10:30

GoogleCodeExporter commented 9 years ago
Just in case, SoapClient(wsdl=..., ns="ru") generated a different XML but still 
the same error:
-------------
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope 
xmlns:ru="http://engine.paymentgate.ru/webservices/merchant" 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header><wsse:Security>...</wsse:Security></soapenv:Header>
<soapenv:Body>
    <ru:getOrderStatusExtended>
    <ru:order><merchantOrderNumber xmlns="http://engine.paymentgate.ru/webservices/merchant">1</merchantOrderNumber></ru:order></ru:getOrderStatusExtended>
</soapenv:Body>
</soapenv:Envelope>
-------------
SoapFault: soap:Server: Found element 
{http://engine.paymentgate.ru/webservices/merchant}order but could not find 
matching RPC/Literal part
-------------

Original comment by m...@ilyasemenov.com on 29 Aug 2013 at 11:03

GoogleCodeExporter commented 9 years ago
It seems that this webservice requires attributes (orderId, languages), the 
correct request xml according SoapUI is:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:mer="http://engine.paymentgate.ru/webservices/merchant">
   <soapenv:Header/>
   <soapenv:Body>
      <mer:getOrderStatusExtended>
         <order orderId="?" language="?">
            <!--Optional:-->
            <merchantOrderNumber>?</merchantOrderNumber>
         </order>
      </mer:getOrderStatusExtended>
   </soapenv:Body>
</soapenv:Envelope>

Could you open a new issue? 
(as the original topics -wsdl imports and namespaces- are fixed now)

Original comment by reingart@gmail.com on 29 Aug 2013 at 2:39