1 2 Introduction 3 4wsdlpull is a C++ web services client library. It includes a WSDL 5Parser,a XML Schema Parser and Validator and XML Parser and serializer 6and an API and command line tool for dynamic WSDL inspection and 7invocation. 8 9wsdlpull comes with a generic web service client.Using wsdlpull's /wsdl/ 10tool you can invoke most web services from command line without writing 11any code. 12 13 14 Table of Contents 15 16 1. *Overview 17 2. *Download <http://sf.net/projects/wsdlpull>* 18 3. *Installation 19 4. *Usage 20 5. *Writing a web service client 21 6. *Parsing WSDL* 22 7. *Using the Schema Parser API 23 8. *Using the schema validation tool 24 9. *Examples 25 10. *XML processing 26 11. *API Documentation <documentation.html>* 27 12. *wsdlpull Discussion <http://groups.yahoo.com/group/wsdlpull>* 28 13. *Reporting bugs and Submitting patches 29 30------------------------------------------------------------------------ 31 32 33 Overview 34 35wsdlpull uses the xml pull api to parse a WSDL1.1 document. This makes 36wsdlpull /highly efficient/ which is why you can process and invoke a 37WSDL in no time. 38 39The Web service Invocation API <#client> allows you to /dynamically/ 40inspect and invoke a web service. Unlike other toolkits there is no need 41to generate stubs or type serializers. 42You can use the dynamic invocation API to write your own web service 43clients in one step. Writing a web service client involves providing the 44WSDL URL,setting the operation,the input types and getting back the 45results. No knowledge of SOAP is needed to write a web service client 46using wsdlpull. The invocation API is quite protocol independent and 47focusses on presenting a simple and intutive interface and abstracts 48away protocol specific details. 49 50wsdlpull comes with a generic web service invocation tool /wsdl/ 51which uses the above API. Both the API and the tool are *very dynamic* 52and allow invocation of WSDLs which have complex types and simple types 53in the schema.Using the /wsdl/ tool you can invoke complex 54web services from command line /without writing any code./ 55 56The WSDL parser <#parse> provides APIs to access various WSDL elements 57such as operations,messages,bindings,port types.Although wsdlpull is 58based on the pull parsing style of xml parsing the API is meant to be 59semantically as close as possible to the standard API for parsing 60WSDL,namely WSDL4J. 61 62The schema parser <#schemap> and validator provides an API for parsing 63XSD schema documents and validating their xml instance documents. The 64schema parser is used to parse the types section of the WSDL document. 65The schema <#schema> tool can be used for many purposes such as 66validating schemas and accessing REST services <#examples>. 67 68The Xml parser and serializer provide a C++ implementation of the XML 69Pull API <http://www.xmlpull.org>.WSDL processing,XSD schema 70processing,sending and receiving SOAP messages use the parser and 71serializer. 72 73Download wsdlpull <http://sourceforge.net/projects/wsdlpull> and follow 74the instructions below. The package has detailed doxygen documentation 75for all the APIs 76 77 78 79------------------------------------------------------------------------ 80 81 82 Installation 83 84Linux/Unix *Installing from source* 85 86Unpack the archive and give the following commands 87./configure --help 88./configure --prefix=%{prefix} [other options] 89make 90make install 91 92This will compile all the targets excluding examples. If you want to 93compile the examples use the --enable-examples option with configure. 94 95Normally ,g++ does optimization of c++ code and it becomes impossible to 96debug.If you wish to debug then do --disable-opt with configure. 97 98For logging related code to be present add --with-log with configure. 99 100To write a web service client using wsdlpull make sure to add the 101$(prefix)/include in your include path and add $(prefix)/libs and -lwsdl 102-lschema -lxmlpull to your LDFLAGS . 103 104*Installing from rpms/debian packages* 105Many packages are available for wsdlpull via various distributions on the web. 106You can install using rpm -i <package name> or dpkg -i <package name> 107 108Windows 109The wsdl.exe is present in the win32 directory.Copy it to the main wsdlpull directory and start using it. 110 111To build users can find MSVC++ project files in the win32 directory. 112Open wsdlpull.dsw in MSVC++ and do a clean build. For logging related code to 113be present add LOGGING in the preprocessor defines of the MSVC++ project 114 115Additionally a windows makefile is included which allows singlethreaded,multighreaded and dll builds. 116 117Since the soap.xsd schema is required for parsing wsdl documents with 118soap binding elements (which means almost all wsdl documents) you need 119to adjust the relative path so that the parser can locate the soap 120binding schema. Soap.cpp file has the path to the soap schema. Hence for 121win32 platforms executables for the wsdl tool is generated in the 122wsdlpull root directory ,and has the path to the soap.xsd schema 123hardcoded relative to the wsdlpull root directory .So be wary before you 124move try to execute this from another location ,because you would have 125to change some code to make it work from other locations. 126 127Some older compilers may give errors with the << operator on Qname.If this is 128the case then change those statments to use the << on Qname::getLocalName(). 129 130------------------------------------------------------------------------ 131 132 133 Usage 134 135wsdlpull has a tool called /wsdl/,a generic web service invocation tool 136which uses the invocation API.Using this command you can see the web 137service operations,their descriptions and provide operation's inputs and 138get the output. 139 140A way to use it is like this. 141 142[user@localhost]wsdl http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl getQuote XYZW 14327.101 144 145If you do not specify the operation name or any of the parameters,the 146tool gives a choice of operations to invoke and prompts for the 147operation's parameters.With the -d option you can also see the 148operation's documentation. 149 150[user@localhost]wsdl http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl 1511.getRate : 152Choose one of the above operations [1-1] :1 153country1:Japan 154country2:India 15546.23 156 157If you just want it in one shot then you can do 158 159[user@localhost]wsdl http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl getRate "United States" India 16043.81 161 162If the parameter is a space separated string make sure you enclose it in 163" " or else the shell would treat it as 2 arguments. 164 165The -l option simply lists the operations of the web service.The below 166command shows how you can see a list of operations available for the 167MovieSearch Web service from www.ignyte.com along with a description of 168what each operation does. 169 170[user@localhost]wsdl -l -d http://www.ignyte.com/webservices/ignyte.whatsshowing.webservice/moviefunctions.asmx?wsdl 1711.GetTheatersAndMovies(This method will retrieve a list of all theaters and the movies playing today.) 1722.GetUpcomingMovies(This method will retrieve a list of all movies that are scheduled to be released in the future and their anticipated release dates.) 173 174The -v options runs the tool in the verbose mode. It displays wsdl 175operations' documentation and also logs the SOAP requests and response. 176 177Invoking the tool with no arguments shows the usage of the command. 178 179The /wsdl/ invocation tool can invoke web services which accept and/or 180return complex types and simple types in their description.If a web 181service needs a complex type then only its constituent simple type 182particles,are passed as inputs. Simple types are validated for basic 183checks and also against any schema provided restrictions such as 184enumeration. For example invoking the instant messenger service from 185/http://www.bindingpoint.com/ws/imalert// involves sending a complex 186type defined as below 187 188 189 <s:element name="SendYahoo"> 190 <s:complexType> 191 <s:sequence> 192 <s:element minOccurs="0" maxOccurs="1" name="LKEY" type="s:string" /> 193 <s:element minOccurs="0" maxOccurs="1" name="FromName" type="s:string" /> 194 <s:element minOccurs="0" maxOccurs="1" name="ToUserID" type="s:string" /> 195 <s:element minOccurs="0" maxOccurs="1" name="Message" type="s:string" /> 196 </s:sequence> 197 </s:complexType> 198 199When you run the /wsdl / tool on the IM web service you will have to 200just enter the 4 simple constituent elements. 201 202[user@localhost wsdls]$wsdl im.wsdl 2031.SendAIM 2042.SendICQ 2053.SendMSN 2064.SendYahoo 207Choose one of the above operations [1-4] :4 208LKEY: ****** 209FromName: Foo 210ToUserID: bar666 211Message:Message1 212### or a one liner 213[user@localhost wsdls]$wsdl im.wsdl SendYahoo ***** Foo bar666 "This is a test message" 214 215Sometimes a schema can specify how many times or a 216range(minOccurs..maxOccurs) a particle can occur inside its content 217model. This is often used to implement arrays by specifiying the 218maxOccurs as unbounded. By using the -o options the /wsdl/ tool prompts 219for occurrences of input parameters. 220 221*Notes* 222 223Obviously there is a limit on the expressive power of providing 224parameters from command line for wsdl invocation. Here are a few notes. 225 226 1. There is no way yet to handle correctly and completely,web 227 services which expect soapenc:Array.Some support exists for web 228 services returning soap arrays since 1.9.5.GoogleSearch/mp3 search 229 works.Although multidimensional SOAP arrays are not and probably 230 never will be supported since SOAP arrays themselves are 231 deprecated as per section 5.2.3 of the WS-I basic profile. 232 2. Web services which return complex derived types cannot be invoked 233 dynamically as of release 1.9.5b. 234 3. A web service which accepts a complex type which has a content 235 model(group,sequence) with possible multiple occurrences can 236 accept only one occurrence via the invocaton API as of 237 1.9.5b.Return complex types can be arbitrarily complex except for 238 the above 2 cases. 239 4. Simple types are validated via facets/restriction provided in the 240 schema.If a simple string type is a restricted by an enumeration 241 with values "Male" and "Female",anything other than those values 242 is considered illegal and the tool exits with an error 243 message.There is no way as of now to turn this kind of checking off. 244 5. There is no way as of now to specify occurrence constraints 245 (minOccurs, maxOccurs) of particles in complex types in the input 246 of an operation using the command line in the non interactive 247 mode.Using -o starts the tool in the interactive mode. The 248 invocation API however supports multiple occurences. If you want 249 anything more than the default behavior of the wsdl tool then you 250 should consider writing your own client using the api. 251 6. HTTP POST needed to send SOAP messages and HTTP GET needed to 252 fetch WSDL uri's are done using curl on linux/unix 253 platforms.libcurl is available on most platforms so shouldn't be a 254 problem though. 255 256 2572,3,4 are likely to be fixed in later releases. 258 259 260 261------------------------------------------------------------------------ 262 263 264 Writing a web service client 265 266You can use the invocation API to write a web service client. Unlike 267many other toolkits you don't need to generate skeleton stubs or write 268type serializers or even have any knowledge of SOAP.The below example 269illustrates how to write a client for the StockQuotes.wsdl web service 270included in the distribution. 271 272 273<s:element name="GetQuotes"> 274<s:complexType> 275<s:sequence> 276<s:element minOccurs="0" maxOccurs="1" name="QuoteTicker" type="s:string" /> 277</s:sequence> 278</s:complexType> 279</s:element> 280<s:element name="GetQuotesResponse"> 281<s:complexType> 282<s:sequence> 283<s:element minOccurs="0" maxOccurs="1" name="GetQuotesResult" 284type="s0:ArrayOfQuote" /> 285</s:sequence> 286</s:complexType> 287</s:element> 288<s:complexType name="ArrayOfQuote"> 289<s:sequence> 290<s:element minOccurs="0" maxOccurs="unbounded" name="Quote" 291type="s0:Quote" /> 292</s:sequence> 293</s:complexType> 294<s:complexType name="Quote"> 295<s:sequence> 296<s:element minOccurs="0" maxOccurs="1" name="CompanyName" type="s:string" /> 297<s:element minOccurs="0" maxOccurs="1" name="StockTicker" type="s:string" /> 298<s:element minOccurs="0" maxOccurs="1" name="StockQuote" type="s:string" /> 299<s:element minOccurs="0" maxOccurs="1" name="LastUpdated" type="s:string" /> 300<s:element minOccurs="0" maxOccurs="1" name="Change" type="s:string" /> 301<s:element minOccurs="0" maxOccurs="1" name="OpenPrice" type="s:string" /> 302<s:element minOccurs="0" maxOccurs="1" name="DayHighPrice" 303type="s:string" /> 304<s:element minOccurs="0" maxOccurs="1" name="DayLowPrice" type="s:string" /> 305<s:element minOccurs="0" maxOccurs="1" name="Volume" type="s:string" /> 306<s:element minOccurs="0" maxOccurs="1" name="MarketCap" type="s:string" /> 307<s:element minOccurs="0" maxOccurs="1" name="YearRange" type="s:string" /> 308</s:sequence> 309</s:complexType> 310<s:element name="ArrayOfQuote" nillable="true" type="s0:ArrayOfQuote" /> 311</s:schema> 312 313 314 315<message name="GetQuotesSoapIn"> 316<part name="parameters" element="s0:GetQuotes" /> 317</message> 318<message name="GetQuotesSoapOut"> 319<part name="parameters" element="s0:GetQuotesResponse" /> 320</message> 321 322 323 324<portType name="StockQuotesSoap"> 325<operation name="GetStockQuotes"> 326<input name="GetQuotes" message="s0:GetQuotesSoapIn" /> 327<output name="GetQuotes" message="s0:GetQuotesSoapOut" /> 328</operation> 329</portType> 330 331 332First,include the relevant header file. 333 334| #include <wsdlparser/WsdlInvoker.h> | 335 336The convention while including files from wsdlpull is to specify the 337root include directory in the include path and then specify the actually 338directory while #include -ing. Files belonging to the schema parser 339would be included like 340 341| #include <schemaparser/SchemaParser.h>| 342 343Create an instance of the WsdlInvoker. 344 345| | 346 347 348 WsdlInvoker invoker; 349 if (!invoker.setWSDLUri("StockQuotes.wsdl")) { 350 std::cerr<<invoker.errors()<<std::endl; return 2; 351 } 352 353 354Now set the operation .Before that you can also get a list of operations 355available 356 357| | 358 359 360 std::vector<std::string> ops; 361 invoker.getOperations(ops); 362 if(!invoker.setOperation("GetStockQuotes")){ 363 364 std::cerr<<"Error calling GetStockQuotes "<<std::endl; 365 return 2; 366 } 367 368Set the input values. Setting the input values can be done by passing a 369void* or by passing a string representation of the value. 370The string representation is provided for convinience so that you can 371just read something from the standard input using scanf or cin and pass 372it on to the WsdlInvoker to do the type validation check.You dont have 373to bother about reading an int or a float or a string.Just read the data 374from the stream as a string and allow the invoker to do all the validation. 375 376| | 377 378 379 if (invoker.status()){ 380 381 std::string ticker("XYZ"); 382 if (!invoker.setValue("QuoteTicker",(void*)(&ticker))){ 383 384 std::cerr<<"Incorrect input value "<<ticker<<std::endl; 385 return 2; 386 } 387 388 if (invoker.invoke()){ 389 390 Schema::Type type; 391 void *val = invoker.getValue("OpenPrice",type); 392 //type is a string 393 cout<<*((std::string*)val)<<std::endl; 394 } 395 396The above example is illustrates the simple API usage. However you can 397get more control over the input and output with more of the API. You can 398set the occurrence constraints like this. | | 399 400 401 std::vector<std::string> stocks 402 stocks.push_back("IBM"); 403 stocks.push_back("YHOO"); 404 stocks.push_back("MSFT"); 405 stocks.push_back("MOT"); 406 //4 occurrences of the <QuoteTicker> element 407 invoker.setValue("QuoteTicker",stocks); 408 409 410After invoking the web service ,you can get the individual elements 411using getValue() like above. 412 413The getValue() method returns a type via reference ,which can be used to 414typecast the return void*. xsdType:string is serialized as std::string 415and others are fairly obvious such as int and float for xsdType:int and 416xsdType:float respectively. 417 418See examples/stocks/stocks.cpp to see the above code in action. Apart 419from the simple style above there are apis to examine all the inputs of 420a web service and set values with occurrence constraints for each of 421them. || 422 423 int getNextInput(std::string & param ,Schema::Type & type,int & min,int & max); 424 425The above API exposes all the simple types that need to be passed as 426input.Even if a web service accepts a complex type ,calls to 427getNextInput exposes the constituent particles which are of a simple 428type. You can either use this style or directly set the value using 429setValue() as shown earlier. 430 431Outputs can be read either using getValue() or by getting the 432TypeContainer for all the message response parts using 433getNextOutput().The TypeContainer interface is more complicated but 434allows better access to the XML structure,such as reading 435attributes,multiple occurrences etc. The api is in the 436schemaparser/TypeContainer.h 437 438The generic web service invocation tool 'wsdl' in wsdlparser/wsdl.cpp 439uses the complex style.Check that for an example 440 441 442 443------------------------------------------------------------------------ 444 445 446 Parsing and validating a schema 447 448wsdlpull also includes a schema parser. The Schema parser itself can be 449used in isolation to parse xsd schemas. The schema parser can validate 450an instance document of the xsd schema just parsed. 451Create a SchemaParser object 452|| 453 454 #include <schemaparser/SchemaParser.h> 455 #include <schemaparser/SchemaValidator.h> 456 ... 457 SchemaParser sParser= new SchemaParser(uri,"target namespace"); 458 459 460Calling SchemaParser::parseSchemaTag() parses the entire document. Use 461getter methods to get types/elements and attributes .Use SchemaValidator 462to parse an instance of a type or element by calling 463| | 464 465 SchemaValidator::validate(int xType, XmlPullParser* ,TypeContainer*) 466 467 468The TypeContainer returned is a recursvive container structure holding 469the values of xml elements and attributes in the instance. See 470src/schemaparser/schema.cpp to understand how to do this. 471 472See the doxygen documentation of the API that comes with the package 473 474 475 476------------------------------------------------------------------------ 477 478 479 Schema Validation tool 480 481wsdlpull includes a schema validation tool 'schema' Take the schema 482below which has a bunch of restricted schema types 483 484<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 485<xsd:simpleType name="USState"> 486 <xsd:restriction base="xsd:string"> 487 <xsd:enumeration value="AK"/> 488 <xsd:enumeration value="AL"/> 489 <xsd:enumeration value="AR"/> 490 <xsd:enumeration value="TX"/> 491 <xsd:enumeration value="IL"/> 492 <xsd:enumeration value="FL"/> 493 </xsd:restriction> 494</xsd:simpleType> 495 496<xsd:simpleType name="myInteger"> 497 <xsd:restriction base="xsd:integer"> 498 <xsd:minExclusive value="10000"/> 499 <xsd:maxInclusive value="99999"/> 500 </xsd:restriction> 501</xsd:simpleType> 502 503<xsd:simpleType name="listOfMyIntType"> 504 <xsd:list itemType="myInteger"/> 505</xsd:simpleType> 506 507<xsd:simpleType name="listOfInt"> 508 <xsd:list itemType="xsd:int"/> 509</xsd:simpleType> 510 511<xsd:simpleType name="USStateList"> 512 <xsd:list itemType="USState"/> 513</xsd:simpleType> 514 515<xsd:simpleType name="SixUSStates"> 516 <xsd:restriction base="USStateList"> 517 <xsd:length value="8"/> 518 </xsd:restriction> 519</xsd:simpleType> 520 521<xsd:element name="listOfMyInt" type="listOfMyIntType"/> 522<xsd:element name="sixStates" type="SixUSStates"/> 523</xsd:schema> 524 525 526The below xml is an instance of the above schema which we want to 527validate with the /schema/ tool. 528 529 530<listOfMyInt>20003 15037 95977 95945</listOfMyInt> 531<listOfMyInt>10000 10001</listOfMyInt> 532<sixStates>PA NY CA NY LA AK</sixStates> 533<sixStates>FL IL</sixStates> 534<listOfMyInt>3 4 5</listOfMyInt> 535<sixStates>FL IL AK</sixStates> 536<sixStates>PA IL AK</sixStates> 537 538The output below catches the errors that some of the data types have wrt 539the schema,including violation of enumeration,length,max and min facets. 540 541 [user@localhost]schema list.xsd -i list.xml 542Successfully parsed schema 543:listOfMyInt 20003 15037 95977 95945 544:listOfMyInt 10000 10001 -->Invalid value for data type 545:sixStates PA NY CA NY LA AK -->Invalid value for data type 546:sixStates FL IL -->Invalid value for data type 547:listOfMyInt 3 4 5 -->Invalid value for data type 548:sixStates FL IL AK 549:sixStates PA IL AK -->Invalid value for data type 550 551The tool can flag many other validation errors including violation of 552occurrence constraints,and missing attributes 553 554 555 556------------------------------------------------------------------------ 557 558 559 Examples 560 561Invoking the popular stock quotes web service and the currency exchange 562services 563 564wsdl http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl getQuote SYMBOL 565wsdl http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl getRate "United States" India 566 567Get the local time in you city 568 569wsdl http://www.nanonull.com/TimeService/TimeService.asmx?wsdl getCityTime Tokyo 570 571Or a more complex google search whose wsdl is included in the test 572directory.Get the first 5 google search results for 'wsdlpull' 573 574wsdl GoogleSearch.wsdl doGoogleSearch "****license-key****" wsdlpull 1 5 0 1 1 1 1 1 575 576Get a dictionary/thesarus on your command line 577 578wsdl http://services.aonaware.com/DictService/DictService.asmx?WSDL DefineInDict wn thesaurus 579wsdl http://services.aonaware.com/DictService/DictService.asmx?WSDL DefineInDict moby-thes thesaurus 580 581Use the /schema/ tool to access the Yahoo REST API like this below to 582search for Madonna video. 583 584schema 585http://api.search.yahoo.com/VideoSearchService/V1/VideoSearchResponse.xsd 586-i 587"http://api.search.yahoo.com/VideoSearchService/V1/videoSearch?appid=YahooDemo&query=madonna&results=1" 588 589 590The below code returns a list of movies running within a radius of 3 591miles from Beverly Hills,CA.The result is a huge list but takes hardly a 592few seconds on a high speed connection to parse the wsdl,send requests 593and get back the response! 594 595wsdl 596http://www.ignyte.com/webservices/ignyte.whatsshowing.webservice/moviefunctions.asmx?wsdl GetTheatersAndMovies 90209 3 597 598 599------------------------------------------------------------------------ 600 601 602 Xml Processing 603 604XML parser and serializer can be used to handle XML .The api is the xml 605pull api <http://www.xmlpull.org> and can be used in the same 606fashion.The roundtrip example in examples/xml gives a demonstration. 607 608 609 610------------------------------------------------------------------------ 611 612 613 Reporting Bugs and Submitting patches 614 615Send a bug report to http://groups.yahoo.com/group/wsdlpull or to the 616author <mailto:vivek200120@users.sourceforge.net?subject=wsdlpull>. 617You may also use the sourceforge.net tracker. 618 619If you are submitting a patch then do send the diffs either on the 620mailing list or to the author.Also send a brief description of the patch 621and whether you tested it or if it needs testing. If you need to check 622in to the CVS contact the author for developer access. 623 624Before submitting a patch ,please perform some unit tests to ensure if 625the fix hasnt broken any existing functionality. 626 627 1. If the fix is in the xml parser then run the roundtrip example on 628 as many xml files as possible.Atleast on all the wsdl,schema and 629 xml files that come in the test directory. 630 2. If the fix is in the schema parser then build and run the /schema/ 631 tool on the schema files and their instances in the test/schema 632 directory. 633 3. If the fix is in the wsdl parser then invoke the web services in 634 the test/wsdls directory and check if they work You must atleast 635 test one RPC style web service and one Doc/Literal style from the 636 test suite. 637 638If you fixed the xml parser then you must do all of the above,If you 639fixed the schema parser you need to do steps 2 and 3. If you fixed 640something in the wsdlparser,test step 3. If what you fixed was in one of 641the two tools /wsdl/ or /schema/ or in the examples then test them as 642instructed in the documentation of the tools. 643 644 645If you are reporting a bug with the invocation tool make sure to run 646with -v option and send the SOAP request and response along with a link 647to the WSDL 648 649------------------------------------------------------------------------ 650 651 652 Authors 653 654Vivek Krishna <mailto:vivek200120@users.sourceforge.net> 655SourceForge.net Logo <http://sourceforge.net> 656