Monday, September 21, 2009

Call Web service from QTP through XSL transformation

It all started with issues at work – again. I had to plan how to call Web services as part of our testing project. As I didn’t like the clumsy QTP add-in facilities for web services, I browsed for better solution. I went through several options. One of them was Stefan Thelenius’ articles on XML automation. I played with it and I was not satisfied. It required too much typing and that makes it error-prone.

Then I came across Web Service Proxy generator using XSLT targeting VBScript and JavaScript. I wonder why this brilliant idea was not utilized before in greater scale. In essence, it is very simple.

The idea

Web services are described by Webservices Description Language (WSDL). WSDL itself is XML. XSLT on the other hand are used to transform XML documents into other formats. Then why not to use XSL to transform a WSDL to something useful? This is what Jacco Vonk presented in his article and went further. He transforms the WSDL into VBScript code ready for use. (JavaScript code is also creatable but I don’t care as QTP doesn’t care also). The VBScript code contains one or more proxy classes and functions that you can use to invoke the Web service described by the WSDL.

The issues

I picked up the idea and upgraded Jacco Vonk’s XSLT. I tried it with several WSDLs and I found several issues.

The first one breaking the generated VBScript code was that the WSDL target namespace ended sometimes with '/' and sometimes it did not. I resolved it by introducing XSLT variable serviceNamespace.

The second issue was that XSD double type was not trapped. Simple – just added one more check in the long lines starting with xsl:if.

Next I added type casting to string at several places and replaced '+' with '&' for string concatenation.

The biggest fight

that I fought though was with the namespaces. Different WSDLs use different prefixes for the namespaces and especially for http://www.w3.org/2001/XMLSchema. This namespace is used to define the Web service response types. Correct recognition of these return types was crucial for the generation of the correct types in the VBScript code. So, how do you find the prefix for a namespace? XPath gives us fantastic instruments to traverse, search and filter XML but mainly for XML main body elements and attributes. Not so easy with namespaces and their prefixes in the root node. After a week experimenting unsuccessfully with XPath expressions, I finally found an article at IBM site that resolved my issue almost at once.

Apparently the idea of transforming WSDL was not so new after all. I still wonder why it is not utilized wider and better. Or I just did not find the info?

The article Processing WSDL documents with XSLT discussed exactly the issues I had. Unfortunately this was not enough. After a lot of trials and errors I realized that declaring variable for XSD Schema prefix at the top of the stylesheet is not sufficient. It had to be declared in every template that uses it. Finally it worked.

At least I thought so. Next issue was that SOAP responses were arbitrary. They were using their own prefixes… So, instead of fighting, I decided to work around the problem and amended ‘TextBetween’ function to strip out the namespace prefixes out of the response.

There are certainly more issues to be resolved - for example when response is more complex than a single return value. I suspect that more namespace issue might arise. So far, so good – it worked out.

Wrap it up

The final step was to utilize all the above in QTP. I intended to use Microsoft command-line utility to execute XSLT when I came across this article. It made me slap my forehead. Why use external tool when I can do it directly in QTP through .NET? This is how the final solution got its shape.

Limitations and to do

So far it works with simple Web services that return single value or object with simple member types. I haven’t work out the situation when the response is an array of values or else. I also haven’t tested yet this solution in production environment so, please, be cautious.
Note also that this is still very experimental and I did it for fun.

Download and how to use it

Use the code of the sample QTP test - uncomment the code blocks to test with different Web services. Associate the code library required by the QTP test. Essential is the XSL template. Find them all here.

P.S. Did I mention that the debugging was a nightmare?

6 comments:

Nimrod Astrahan said...

Amazing ! how didn't anyone think of that yet...
but the xsl template link bring to the library file.. could you please post the xsl, or reply me at n...@g...l.com

hyndavi said...

Can any one confirm me that, whether we can use QTP in production environment or not?

Phaethon said...

It all depends on where you're coming from. Whenever I see an XML I need something from, XSLT comes to mind. Although I could have given up easier than you, with the nightmare SOAP sometimes is.

lio said...

Hi
This is just what I was looking for !

It seems that the link to XSL is not correct.

It is the same as the function link

Can you please fix it ?

DragD said...

Link to xslt fixed.

Vinodh said...

DragD,

seems very interesting. The links are broken. Can you fix this please

Thanks