wsdlpull is a C++ web services client library. It includes a WSDL Parser,a XML Schema parser and validator and an XML Parser and serializer. It has an API and command line tool for dynamic WSDL inspection and invocation.The command line tool is a generic web service client using which you can invoke most web services from command line without writing any code.

wsdl GetTheatersAndMovies 90210 3
The above command gets all movies showing within 3 miles of Beverly Hills,CA,USA

Table of Contents

  1. Overview
  2. Download
  3. Installation
  4. Usage
  5. Writing a web service client
  6. Parsing WSDL
  7. Using the Schema Parser API
  8. Using the schema validation tool
  9. Examples
  10. XML processing
  11. API Documentation
  12. Browse latest code
  13. wsdlpull Discussion
  14. Reporting bugs and Submitting patches


wsdlpull uses the xml pull api to parse a WSDL1.1 document. This makes wsdlpull highly efficient which is why you can process and invoke a WSDL in no time.

The Web service Invocation API allows you to dynamically inspect and invoke a web service. Unlike other toolkits there is no need to generate stubs or type serializers.
You can use the dynamic invocation API to write your own web service clients in one step. Writing a web service client involves providing the WSDL URL,setting the operation,the input types and getting back the results. No knowledge of SOAP is needed to write a web service client using wsdlpull. The invocation API is quite protocol independent and focusses on presenting a simple and intutive interface and abstracts away protocol specific details.

wsdlpull comes with a generic web service invocation tool wsdl which uses the above API. Both the API and the tool are very dynamic and allow invocation of WSDLs which have complex types and simple types in the schema.Using the wsdl tool you can invoke complex web services from command line without writing any code.

The WSDL parser provides APIs to access various WSDL elements  such as operations,messages,bindings,port types.Although wsdlpull is based on the pull parsing style of xml parsing the API is meant to be semantically as close as possible to the standard API for parsing WSDL,namely WSDL4J.

The schema parser and validator provides an API for parsing XSD schema documents and validating their xml instance documents. The schema parser is used to parse the types section of the WSDL document.
The schema tool can be used for many purposes such as validating schemas and accessing REST services.

The Xml parser and serializer provide a C++ implementation of the XML Pull API.WSDL processing,XSD schema processing,sending and receiving SOAP messages use the parser and serializer.

Download wsdlpull and follow the instructions below. The package has detailed doxygen documentation for all the APIs

Back to Top


Linux/Unix Installing from source

Unpack the archive and give the following commands 
./configure --help
./configure --prefix=%{prefix} [other options] 
make install 
This will compile all the targets excluding examples. If you want to compile the examples use the --enable-examples option with configure.

Normally ,g++ does optimization of c++ code and it becomes impossible to debug.If you wish to debug then do --disable-opt with configure.

For logging related code to be present add --with-log with configure.

To write a web service client using wsdlpull make sure to add the $(prefix)/include in your include path and add $(prefix)/libs and -lwsdl -lschema -lxmlpull to your LDFLAGS .

Installing from rpms

RPMs for Fedora core 3 are available on the Sourceforge site. Dag Wieers's RPM repository has RPMs for many platforms.


Win32 users can find MSVC++ project files in the win32 directory.Open wsdlpull.dsw in MSVC++ and do a clean build. Additionally makefiles are provided for DLL and single/multi threaded builds. For logging related code to be present add LOGGING in the preprocessor defines of the MSVC++ project.
The path to the SOAP schemas required for parsing is set to "src/schemas" by default.This can be overriden at compile time by defining the SCHEMADIR flag. If try to execute the wsdl tool from another location,you would have to recompile with the new SCHEMADIR.

Back to Top


wsdlpull has a tool called wsdl,a generic web service invocation tool which uses the invocation API.Using this command you can see the web service operations,their descriptions and provide operation's inputs and get the output.

A way to use it is like this.

[user@localhost]wsdl getQuote XYZW

If you do not specify the operation name or any of the parameters,the tool gives a choice of operations to invoke and prompts for the operation's parameters.With the -d option you can also see the operation's documentation.

1.getRate :
Choose one of the above operations [1-1] :1
If you just want it in one shot then you can do
[user@localhost]wsdl getRate "United States" India

If the parameter is a space separated string make sure you enclose it in " " or else the shell would treat it as 2 arguments.

The -l option simply lists the operations of the web service.The below command shows how you can see a list of operations available for the MovieSearch Web service from along with a description of what each operation does.

[user@localhost]wsdl -l -d 
1.GetTheatersAndMovies(This method will retrieve a list of all theaters and the movies playing today.)
2.GetUpcomingMovies(This method will retrieve a list of all movies that are scheduled to be released in the future and their anticipated release dates.)

The -v options runs the tool in the verbose mode. It displays wsdl operations' documentation and also logs the SOAP requests and response.

Invoking the tool with no arguments shows the usage of the command.

The wsdl invocation tool can invoke web services which accept and/or return complex types and simple types in their description.If a web service needs a complex type then only its constituent simple type particles,are passed as inputs. Simple types are validated for basic checks and also against any schema provided restrictions such as enumeration. For example invoking the instant messenger service from involves sending a complex type defined as below

      <s:element name="SendYahoo">
            <s:element minOccurs="0" maxOccurs="1" name="LKEY" type="s:string" />
            <s:element minOccurs="0" maxOccurs="1" name="FromName" type="s:string" />
            <s:element minOccurs="0" maxOccurs="1" name="ToUserID" type="s:string" />
            <s:element minOccurs="0" maxOccurs="1" name="Message" type="s:string" />
When you run the wsdl tool on the IM web service you will have to just enter the 4 simple constituent elements.
[user@localhost wsdls]$wsdl im.wsdl 
Choose one of the above operations [1-4] :4
LKEY: ******
FromName: Foo
ToUserID: bar666
### or a one liner 
[user@localhost wsdls]$wsdl im.wsdl SendYahoo   *****   Foo  bar666   "This is a test message"

Sometimes a schema can specify how many times or a range(minOccurs..maxOccurs) a particle can occur inside its content model. This is often used to implement arrays by specifiying the maxOccurs as unbounded. By using the -o options the wsdl tool prompts for occurrences of input parameters.


Obviously there is a limit on the expressive power of providing parameters from command line for wsdl invocation. Here are a few notes.

  1. There is no way yet to handle correctly and completely,web services which expect soapenc:Array.Although multidimensional SOAP arrays are not and probably never will be supported since SOAP arrays themselves are deprecated as per section 5.2.3 of the WS-I basic profile.
  2. Web services which return complex derived types cannot be invoked dynamically
  3. A web service which accepts a complex type which has a content model(group,sequence) with possible multiple occurrences can accept only one occurrence via the invocaton API.Return complex types can be arbitrarily complex except for the above 2 cases.
  4. Simple types are validated via facets/restriction provided in the schema.If a simple string type is a restricted by an enumeration with values "Male" and "Female",anything other than those values is considered illegal and the tool exits with an error message.There is no way as of now to turn this kind of checking off.
  5. There is no way as of now to specify occurrence constraints (minOccurs, maxOccurs) of particles in complex types in the input of an operation using the command line in the non interactive mode.Using -o starts the tool in the interactive mode. The invocation API however supports multiple occurences. If you want anything more than the default behavior of the wsdl tool then you should consider writing your own client using the api.
  6. HTTP POST needed to send SOAP messages and HTTP GET needed to fetch WSDL uri's are done using curl on linux/unix platforms and WinInet API on windows.Both these are widely available so getting invocation to work shouldn't be a problem.

2,3 and 4 are likely to be fixed in later releases.

Back to Top

Writing a web service client

You can use the invocation API to write a web service client. Unlike many other toolkits you don't need to generate skeleton stubs or write type serializers or even have any knowledge of SOAP.The below example illustrates how to write  a client for the StockQuotes.wsdl web service included in the distribution.

<s:element name="GetQuotes">
<s:element minOccurs="0" maxOccurs="1" name="QuoteTicker" type="s:string" />
<s:element name="GetQuotesResponse">
<s:element minOccurs="0" maxOccurs="1" name="GetQuotesResult" type="s0:ArrayOfQuote" />
<s:complexType name="ArrayOfQuote">
<s:element minOccurs="0" maxOccurs="unbounded" name="Quote" type="s0:Quote" />
<s:complexType name="Quote">
<s:element minOccurs="0" maxOccurs="1" name="CompanyName" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="StockTicker" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="StockQuote" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="LastUpdated" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Change" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="OpenPrice" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="DayHighPrice" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="DayLowPrice" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Volume" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="MarketCap" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="YearRange" type="s:string" />
<s:element name="ArrayOfQuote" nillable="true" type="s0:ArrayOfQuote" />

<message name="GetQuotesSoapIn">
<part name="parameters" element="s0:GetQuotes" />
<message name="GetQuotesSoapOut">
<part name="parameters" element="s0:GetQuotesResponse" />

<portType name="StockQuotesSoap">
<operation name="GetStockQuotes">
<input name="GetQuotes" message="s0:GetQuotesSoapIn" />
<output name="GetQuotes" message="s0:GetQuotesSoapOut" />

First,include the relevant header file.

#include <wsdlparser/WsdlInvoker.h>

The convention while including files from wsdlpull is to specify the root include directory in the include path and then specify the actually directory while #include -ing. Files belonging to the schema parser would be included like

#include <schemaparser/SchemaParser.h>

Create an instance of the WsdlInvoker.

  WsdlInvoker invoker; 
  if (!invoker.setWSDLUri("StockQuotes.wsdl")) {
    std::cerr<<invoker.errors()<<std::endl; return 2;

Now set the operation .Before that you can also get a list of operations available

  std::vector<std::string> ops;
      std::cerr<<"Error calling GetStockQuotes "<<std::endl;
      return 2;

Set the input values. Setting the input values can be done by passing a void* or by passing a string representation of the value.
The string representation is provided for convinience so that you can just read something from the standard input using scanf or cin and pass it on to the WsdlInvoker to do the type validation check.You dont have to bother about reading an int or a float or a string.Just read the data from the stream as a string and allow the invoker to do all the validation.

   if (invoker.status()){

       std::string ticker("XYZ");
       if (!invoker.setValue("QuoteTicker",(void*)(&ticker))){
            std::cerr<<"Incorrect input value "<<ticker<<std::endl;
            return 2;

        if (invoker.invoke()){
         Schema::Type type;
         void *val = invoker.getValue("OpenPrice",type);
         //type is a string 

The above example is illustrates the simple API usage. However you can get more control over the input and output with more of the API. You can set the occurrence constraints like this.

     std::vector<std::string> stocks
     //4 occurrences of the <QuoteTicker> element 
After invoking the web service ,you can get the individual elements using getValue() like above.

The getValue() method returns a type via reference ,which can be used to typecast the return void*. xsdType:string is serialized as std::string and others are fairly obvious such as int and float for xsdType:int and xsdType:float respectively.
See examples/stocks/stocks.cpp to see the above code in action. Apart from the simple style above there are apis to examine all the inputs of a web service and set values with occurrence constraints for each of them.
    int getNextInput(std::string & param ,Schema::Type & type,int & min,int & max);
The above API exposes all the simple types that need to be passed as input.Even if a web service accepts a complex type ,calls to getNextInput exposes the constituent particles which are of a simple type. You can either use this style or directly set the value using setValue() as shown earlier.

Outputs can be read either using getValue() or by getting the TypeContainer for all the message response parts using getNextOutput().The TypeContainer interface is more complicated but allows better access to the XML structure,such as reading attributes,multiple occurrences etc. The api is in the schemaparser/TypeContainer.h

The generic web service invocation tool 'wsdl' in wsdlparser/wsdl.cpp uses the complex style.Check that for an example

Back to Top

Parsing WSDL

wsdlpull has a WSDL Parser which can be used to parse and examine the WSDL. Create an instance of the WSDLParser object passing in the url of the wsdl file.
   WsdlParser wp (url, cout); Make sure you include the Wsdlparser header files.    #include <wsdlparser/WsdlParser.h> The parsing process progresses whenever the you start calling WSDLParser::getNextElement (). It parses a top level WSDL element and returns the kind of element just parsed ,which can be one of WsdlParser::START,
Using the return value you can use any of the various getter methods to the get the WSDL elements just parsed. example getBinding() returns a pointer to the binding just parsed. At any time the state of the parser can be queried using WSDLParser::getEventType ,The parsing has ended when the method returns WSDLParser::END.  

     while (wp.getEventType () != WsdlParser::END){
         switch (wp.getNextElement ()) {
           case WsdlParser::DOCUMENTATION:
              cout << wp.getDocumentation () << endl;
           case WsdlParser::TYPES:
              cout << wp.getNumSchemas () << "   schema(s) found" << endl;
           case WsdlParser::MESSAGE:
              cout <<"Message :"<<(wp.getMessage())->getName () << endl; 
          case WsdlParser::PORT_TYPE:
              const PortType * p = wp.getPortType ();
              cout <<"PortType:"<<p->getName () << "  has  " << 
              p->getNumOps () << " operations "<<endl;
              Operation::cOpIterator from,to;
The Error status can be be queried using WsdlParser::status() Even after parsing is over you can use the getter methods to get all the WSDL Elements or query using a valid Qname,for example getPortType(Qname(myNamespace:portType1)) would return reference to the port type whose name is portType1. The below code prints out all the operations in the WSDL #include <wsdlparser/WsdlParser.h>
 PortType::cPortTypeIterator p1,p2;
    Operation::cOpIterator op1,op2;

See the doxygen documentation of the API that comes with the package

Extensibility elements

wsdlpull also supports WSDL extensibility elements.You can add an extensibility schema to your wsdl document and provide an interface to handle the extensibility elements when the parser encounters them. The WSDLExtension class provides the interface.Any one wanting to implement a WSDL extension must implement this abstract interface. In addition a schema describing the WSDL extension if provided ,avoids the task of parsing the extensibility XML again when encountered in the WSDL.
  return "my-namespace";
  return "";
SOAP binding has been parsed this way,so check it out for an example.
Steps involved here are (see Soap.cpp for code details)
  1. Develop a schema for extensibility elements (optionalbut recommended) 
  2. Implement the WSDLExtension interface (see WSDLExtension.h)
  3. The WsdlParser parses all the extensibility schemas before it begins parsing and sets the SchemaParser by calling setSchemaParser on your extension class. The extension can store this for later validation of xml i that occurs in the WSDL document.
  4. Register the handler before you begin the parsing.
        m_soap = new Soap();
        wParser.addExtensibilityHandler (m_soap);
       //Soap derives from WSDLExtension
  5. Iinitiate the parsing by using the getNextElement() method.
  6. Whenever the WSDLParser sees an extensibily element for which it has a registered handler it will call the method    handleElement() or handleAttribute() of the extensibility handler
  7. WsdlExtension::handleElement() gets an instance of the XmlPullParser whose buffer is positioned just before the extensibility element. At this point ,you can either use the xmlpull api to parse the xml stream or if you have a schema for your   extensibility element,simply validate the stream against the schema parser instance which has parsed your extensibility schema and get a TypeContainer which has values populated for all your xml elements and attributes in the type.
  8. WsdlExtension::handleAttribute() again gets the name WSDL element in which the attribute occurred ,its name and an instance of the XmlPullParser. You can get the attribute value using XmlPullParser::getAttributeValue()
  9. WsdlExtension::handleElement() and  WsdlExtension::handleAttribute() need to return a unique id for each element or attribute parsed ,which is greater than start_id (set by the WsdlParser).
Back to Top

Parsing and validating a schema

wsdlpull also includes a schema parser. The Schema parser itself can be used in isolation to parse xsd schemas. The schema parser can validate an instance document of the xsd schema just parsed.
Create a SchemaParser object

  #include <schemaparser/SchemaParser.h>
  #include <schemaparser/SchemaValidator.h>
  SchemaParser sParser= new SchemaParser(uri,"target namespace");

Calling SchemaParser::parseSchemaTag() parses the entire document. Use getter methods to get types/elements and attributes .Use SchemaValidator to parse an instance of a type or element by calling       
 SchemaValidator::validate(int xType, XmlPullParser* ,TypeContainer*)
The TypeContainer returned is a recursvive container structure holding the values of xml elements and attributes in the instance. See src/schemaparser/schema.cpp to understand how to do this.

See the doxygen documentation of the API that comes with the package

Back to Top

Schema Validation tool

wsdlpull includes a schema validation tool 'schema' Take the schema below which has a bunch of restricted schema types

<xsd:schema xmlns:xsd="">
<xsd:simpleType name="USState">
  <xsd:restriction base="xsd:string">
    <xsd:enumeration value="AK"/>
    <xsd:enumeration value="AL"/>
    <xsd:enumeration value="AR"/>
    <xsd:enumeration value="TX"/>
    <xsd:enumeration value="IL"/>
    <xsd:enumeration value="FL"/>

<xsd:simpleType name="myInteger">
  <xsd:restriction base="xsd:integer">
    <xsd:minExclusive value="10000"/>
    <xsd:maxInclusive value="99999"/>

<xsd:simpleType name="listOfMyIntType">
  <xsd:list itemType="myInteger"/>

<xsd:simpleType name="listOfInt">
  <xsd:list itemType="xsd:int"/>

<xsd:simpleType name="USStateList">
 <xsd:list itemType="USState"/>

<xsd:simpleType name="SixUSStates">
 <xsd:restriction base="USStateList">
  <xsd:length value="8"/>

<xsd:element name="listOfMyInt" type="listOfMyIntType"/>
<xsd:element name="sixStates" type="SixUSStates"/>

The below xml is an instance of the above schema which we want to validate with the schema tool.

<listOfMyInt>20003 15037 95977 95945</listOfMyInt>
<listOfMyInt>10000 10001</listOfMyInt>
<sixStates>PA NY CA NY LA AK</sixStates>
<sixStates>FL IL</sixStates>
<listOfMyInt>3 4 5</listOfMyInt>
<sixStates>FL IL AK</sixStates>
<sixStates>PA IL AK</sixStates>

The output below catches the errors that some of the data types have wrt the schema,including violation of enumeration,length,max and min facets.

 [user@localhost]schema list.xsd -i list.xml 
Successfully parsed schema  
:listOfMyInt 20003 15037 95977 95945
:listOfMyInt 10000 10001 -->Invalid value for data type
:sixStates PA NY CA NY LA AK -->Invalid value for data type
:sixStates FL IL -->Invalid value for data type
:listOfMyInt 3 4 5 -->Invalid value for data type
:sixStates FL IL AK
:sixStates PA IL AK -->Invalid value for data type

The tool can flag many other validation errors including violation of occurrence constraints,and missing attributes

Back to Top


Invoking the popular stock quotes web service and the currency exchange services

wsdl getQuote SYMBOL
wsdl getRate "United States" India

Get the local time in you city

wsdl getCityTime Tokyo

Or a more complex google search whose wsdl is included in the test directory.Get the first 5 google search results for 'wsdlpull'

wsdl GoogleSearch.wsdl doGoogleSearch "****license-key****" wsdlpull 1 5 0 1 1 1 1 1

Get a dictionary/thesarus on your command line

wsdl DefineInDict wn thesaurus
wsdl DefineInDict moby-thes thesaurus

Use the schema tool to access the Yahoo REST API like this below to search for Madonna video.

schema -i ""

The below code returns a list of movies running within a radius of 3 miles from Beverly Hills,CA.The result is a huge list but takes hardly a few seconds on a high speed connection to parse the wsdl,send requests and get back the response!

wsdl GetTheatersAndMovies 90209 3

Or get all the web services summaries from response is a huge list but hardly takes a few seconds.

wsdl getAllServiceSummaries

Back to Top

Xml Processing

XML parser and serializer can be used to handle XML .The api is the xml pull api and can be used in the same fashion.The roundtrip example in examples/xml gives a demonstration.

Back to Top

Reporting Bugs and Submitting patches

Send a bug report to or to the author.
You may also use the tracker.

If you are submitting a patch then do send the diffs either on the mailing list or to the author.Also send a brief description of the patch and whether you tested it or if it needs testing. If you need to check in to the CVS contact the author for developer access.

Before submitting a patch ,please perform some unit tests to ensure if the fix hasnt broken any existing functionality.

  1. If the fix is in the xml parser then run the roundtrip example on as many xml files as possible.Atleast on all the wsdl,schema and xml files that come in the test directory.
  2. If the fix is in the schema parser then build and run the schema tool on the schema files and their instances in the test/schema directory.
  3. If the fix is in the wsdl parser then invoke the web services in the test/wsdls directory and check if they work You must atleast test one RPC style web service and one Doc/Literal style from the test suite.
If you fixed the xml parser then you must do all of the above,If you fixed the schema parser you need to do steps 2 and 3. If you fixed something in the wsdlparser,test step 3. If what you fixed was in one of the two tools wsdl or schema or in the examples then test them as instructed in the documentation of the tools.

If you are reporting a bug with the invocation tool make sure to run with -v option and send the SOAP request and response along with a link to the WSDL
Back to Top


Vivek Krishna Logo