Last year I described the general structure of WSDAPI's WSDXML sections and provided some hints for creating and consuming these structures. I've received a few requests since then to provide more concrete examples of how to build these structures in code.
Before we get started, I do recommend you re-read my original post on WSDXML. The relationship between WSDXML_ELEMENT, WSDXML_TYPE, and WSDXML_NODE is an important part of understanding how everything fits together.
Simple example: element with textThe first example will demonstrate how to build a single element with text, but without any attributes or children. If we imagine the "ex" prefix is bound to the http://www.example.org namespace, here's the element we will want to build:
<ex:TestElement>text</ex:TestElement>
Creating this structure is straightforward. It involves two steps:
Here's what it looks like in code.
// All error handling is omitted from this example HRESULT hr = S_OK; IWSDXMLContext *pContext = NULL; WSDXML_NAME *pName = NULL; WSDXML_ELEMENT *pElement = NULL;
hr = WSDXMLCreateContext( &pContext );
hr = pContext->AddNamespace( L"http://www.example.org", L"ex", NULL );
hr = pContext->AddNameToNamespace( L"http://www.example.org", L"TestElement", &pName );
hr = WSDXMLBuildAnyForSingleElement( pName, // pName is copied here, and must be freed separately L"text", &pElement ); // pElement is now complete, and contains: <ex:TestElement>text</ex:TestElement> // cleanup: // WSDFreeLinkedMemory( pElement ); // WSDFreeLinkedMemory( pName ); // pContext->Release();
Note that you can omit the "text" parameter to WSDXMLBuildAnyForSingleElement to generate empty elements. Supplying NULL here would result in <ex:TestElement />
Advanced example: chaining elementsWe'll build on the last example to show how you can create chains of structures. Here's the element we want to build this time:
<ex:ParentElement> <ex:ChildElement>text</ex:ChildElement> <ex:AnotherChildElement /> </ex:ParentElement>
In this case, the steps go like this:
Important: see section below on cleaning up WSDXML structures. Also note that you only need to call IWSDXMLContext::AddNamespace once for a given namespace--it is not necessary to call it for every name you add.
Here's some example code:
// Use steps above to create pParentElement, pChildElement, // and pAnotherChildElement
hr = WSDXMLAddChild( pParentElement, pChildElement );
hr = WSDXMLAddSibling( pChildElement, pAnotherChildElement ); // It is also acceptable to call // WSDXMLAddChild( pParentElement, pAnotherChildElement);
// cleanup: // WSDFreeLinkedMemory( pParentElement ); // Use WSDFreeLinkedMemory to destroy WSDXML_NAME objects // extracted from IWSDXMLContext // DO NOT FREE pChildElement or pAnotherChildElement; // they are attached to pParentElement
Destroying WSDXML structuresAt first glance, it may seem complex to destroy these structures, but they're designed to be simple. You only need to follow a few simple rules to write robust and leak-free WSDXML code: