Associated Files: Facade.zip
Most software developers, irrespective of the language they are using, will be faced with the task of re-writing code for reading/writing application data and configuration files. Each new application seems to have slightly different requirements for these files and much time is spent altering and adapting old code.
In an attempt to avoid the above situation, I started using XML for both of these file types. Microsoft's XML Parser, via a parser 'facade' class, was used for the basic read and write operations along with some error checking. All I would need to do for any new application, would be to convert the application data to XML and call the appropriate facade method.
Once I started using the parser, I quickly discovered that you could run complex queries against the recorded XML data, using the parser's XPath language. This added a whole new level of flexibility to the retrieval and display of application data. As a bonus, with the release of Microsoft Office 2007 and its Open XML file formats, applications can now conceivably generate files which can be used directly by Word, Excel or Powerpoint.
If you have not used Microsoft's parser in a C++ environment before, the rest of this article should help 'kick start' your development activities with this tool. I have assumed the reader has a basic knowledge of COM/ATL development - a detailed discussion of the associated data types however, lies outwith the scope of this article.
So, as a first step, you should download a copy of the parser SDK from the MSDN download page. The current version, at the time of writing, is six. It includes the parser dlls and the appropriate header and lib files. Once you have installed the complete SDK, set up your Visual Studio include and lib file paths to point to the corresponding SDK directories.
In your application include the header file msxml6.h and, in project properties, insert msxml6.lib in the linker 'Additional Dependencies' section. You are now ready to create an instance of the parser via a call to CoCreateInstance, as detailed below.
::CoCreateInstance(CLSID_DOMDocument60, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument,
(void**)&m_pXMLDoc);
In the above function call, CLSID_DOMDocument60 uniquely identifies the version number of the XML parser - there may be several versions of the parser installed on the host PC. IID_IXMLDOMDocument indicates the desired interface, to be returned via m_pXMLDoc, when the parser is created. In this case, CoCreateInstance function should return a value of S_OK.
Assuming that CoCreateInstance has completed successfully and a valid document interface pointer has been obtained, you should now set any required parser properties before loading an XML file. As a minimum, you should set the parser async and SelectionLanguage properties as detailed below.
VARIANT_BOOL vAsync = VARIANT_FALSE;
m_pXMLDoc->put_async(vAsync);
CComVariant vSyntax("XPath");
BSTR bstrLanguage = ::SysAllocString(L"SelectionLanguage");
m_pXMLDoc->setProperty(bstrLanguage, vSyntax);
Consult the MSXML 6.0 Parser SDK help files for a complete list of parameters and their associated values.
Now, to load an XML file, simply call the document 'load' method. Note, the contents of the current parser document will automatically be discarded when new XML data is read from file. Use the document 'save' method if you need to retain any changes to the existing document, prior to loading new XML data. Loading an XML document into the parser is detailed below.
VARIANT_BOOL vStatus = VARIANT_FALSE;
CComVariant vXMLFile(bstrFilename);
m_pXMLDoc->load(vXMLFile, &vStatus);
where bstrFilename is the full path of the target XML file. You should check that the load function returns S_OK and that the vStatus parameter has a value of VARIANT_TRUE. You can now query the document, or call other document interface methods to alter the data, as required.
A 'bare bones' parser facade class, based on the details presented above, can be downloaded from the ayrware downloads page.