Delphi Clinic | C++Builder Gate | Training & Consultancy | Delphi Notes Weblog | Dr.Bob's Webshop |
![]() |
![]() |
![]() |
|
C++Builder 6
This article will explain how to consume existing Web Services using C++Builder 6 (either Professional or Enterprise).
In this article, I will use a Web Service to search the web using the Google search engine.
Not the official Google search engine (which is a bite more complex, and for which you need to register yourself first), but a simple one implemented by Santra Technology in MS Visual Studio .NET.
The main reason why I've decided to use C++Builder 6 to consume a Web Service written in another environment, is to illustrate the cross-language nature of Web Services right from the start.
Google
The example Web Service that we will be using in this article is the GoogleSearch, which used to be available on the internet as http://rob.santra.com/webservices/public/google/ with the formal WSDL definition at http://rob.santra.com/webservices/public/google/index.asmx?WSDL.
Using a browser such as Internet Explorer, we can view the WSDL (Web Services Description Language) of this web service.
More useful, however, is to take this WSDL URL and feed it to C++Builder 6 in order to generate an import unit that we can use in our own applications.
C++Builder 6
Start C++Builder 6 (professional or enterprise), and save the new default project (or create a new one).
Save the main form in file SearchForm.cpp and the project itself in Google42.bpr.
Like I said, before we can use the GoogleSearch web service, we first need to create a C++ import unit based on the WSDL definition.
This can be done using the WSDL Importer.
Do File | New - Other, and go to the WebServices tab of the Object Repository.
Here, you'll find four SOAP specific wizards (C++Builder 6 professional users will only find the WSDL Importer wizard, but can still work along with this article, because that's the only wizard we'll be using this time).
GetGoogleSearchSoap()
Now, return to the SearchForm unit, and add the generated index.h header file to this unit (with File | Include Unit Hdr), so we can access the GetGoogleSearchSoap() to return the GoogleSearchSoap interface and its methods.
But before we can call this function, let's first finish the Google Search Form itself.
For this, we need a TEdit, a TMemo and a TButton components.
Call them edtSearch, memResult and btnGoogle.
Clear the contents of edtSearch and edtMemo, and give it a nice caption, as can be seen in the follow screenshot:
void __fastcall TForm1::btnGoogleClick(TObject *Sender) { memResult->Lines->Text = GetGoogleSearchSoap()->search(edtSearch->Text); }Using this event handler, we can search for the words Borland, User and Group, which combined result in www.richplum.co.uk as first entry (and second one, by the way). A result that satisfies me (as new webmaster of the UK-BUG website). The result comes in a bit of a new fashion, however: as an XML document, formatted as follows:
<search_results> <item id="1" url="http://www.richplum.co.uk/" /> <item id="2" url="http://www.richplum.co.uk/html/books.asp" /> <item id="3" url="http://www.borland.com/programs/usergroups/" /> <item id="4" url="http://www.borland.com/programs/usergroups/uglist.html" /> <item id="5" url="http://homepages.borland.com/oregondug/" /> <item id="6" url="http://linux.org.mt/" /> <item id="7" url="http://www.linux.org.tr/" /> <item id="8" url="http://www.compinfo-center.com/ugrp.htm" /> <item id="9" url="http://www.ugvendors.com/companies/borland.htm" /> <item id="10" url="http://e-web.ecommsite.com/philbug/cms/" /> </search_results>Darn. Does this mean we have to parse the entire result in order to list the URLs? Well, it would, if we didn't know or remember that C++Builder 6 Enterprise comes with a nice tool called the XML Mapper, which is able to map any XML document to a dataset that can be loaded by a ClientDataSet. So, let's save the above example in file google.xml and start the XML Mapper to see how hard it can be to transform this into something more useful.
XML Mapper
The XML Mapper can be found in the Tools menu of C++Builder, but also as a separate icon in the C++Builder group.
Both point to the same executable, obviously.
Start the XML Mapper, and load the google.xml file, which displays the structure of this rather flat XML file in the left pane of the XML Mapper.
The search_results consists of one node that has two attributes: id and url.
One important thing to note is the Max Length value of the url attribute, which is set to 54 (based on the sample data in the XML document).
This may be far too small to contain some of the longer URLs, so let's change this to 255 just in case:
XML Transformation
Now, get back to the SearchForm, and remove the memResult.
Instead, drop a XMLTransformProvider component as well as a ClientDataSet, DataSource and DBGrid.
The XMLTransformProvider will transform the generated XML document into a data packet, which can be used by the ClientDataSet to display inside the DBGrid component.
Make sure the DataSource property of the DBGrid component points to the DataSource component, and the DataSet property of the DataSource component points to the ClientDataSet component.
The ClientDataSet component should set its ProviderName property to the XMLTransformProvider (you can select this one from the drop-down combobox in the Object Inspector).
Finally, the XMLTransformProvider should get two properties assigned.
The first one is the TransformationFile sub-property of the TransformRead property, which should point to the ToDp.xrt file that we generated using the XML Mapper.
The second property that we must give a value is the XMLDataFile property.
This one must point to the XML file that was received by the call to GoogleSearchSoap.
In our example case, we can point it to google.xml.
However, this also means that we must change the call to search() and in fact make sure to save the resulting XML document in the google.xml document.
Once we re-open the ClientDataSet, the XML document will be transformed again, and provided by the XML TransformProvider component.
In code, the new OnClick event handler is as follows:
void __fastcall TForm1::btnGoogleClick(TObject *Sender) { ClientDataSet1->Close(); XMLTransformProvider1->CacheData = false; TStringList* S = new TStringList(); try { S->Add(GetGoogleSearchSoap()->search(edtSearch->Text)); S->SaveToFile("google.xml"); } __finally { S->Free(); } ClientDataSet1->Open(); }Note that I'm using a TStringList as convenient way to load the resulting XML document and save it to disk. Using this StringList, we can also display the original XML document in a Memo or use the contents for debugging purposes. The final application can be seen in figure 8, which also contains a button to Jump to the selected URL:
void __fastcall TForm1::btnJumpClick(TObject *Sender) { ShellExecute(0,"open",ClientDataSet1->FieldByName("url")->AsString.c_str(),0,0,0); }The result is a small Windows application that can be used to enter a number of search words, return the top 10 URLs, and jump directly to one of these pages when needed. And you can integrate this feature in your own applications as well, of course. As long as an internet connection is available to talk to the GoogleSearchSoap web service (which in turn probably needs to talk to Google itself).
Conclusion
In this article, I've tried to explain how to consume Web Services with C++Builder 6.
We've seen how to generate the import files based on a WSDL definition of the Web Service, and how to actually call the methods from the Web Service.
We've even seen how to use the XML Mapper, which was required to transform the resulting XML document into a data packet. For more information about SOAP and Web Services in C++Builder, Delphi, Kylix or JBuilder, check out my SOAP Bubbles website at http://www.drbob42.com/SOAP.