Using MSXML 3.0 with CMarkupMSXML

XPath and other functionality available in MSXML 3.0 is available in CMarkupMSXML which prior to release 6.2 only used the first release of MSXML. To get MSXML 3.0 functionality, download CMarkup release 6.2 or later (the special 6.11 release of CMarkupMSXML is included in both CMarkup 6.2 evaluation and developer versions), and read the following directions:

Add MARKUP_MSXML3 to your Project Settings C/C++ Preprocessor Definitions (in addition to MARKUP_MSXML if its in the CMarkup project). The MSXML 3.0 dependency is completely optional. The primary differences (see #ifdef MARKUP_MSXML3) are in the CreateInstance identifier and the MSXML2 namespace. The MSXML3 version now exposes the m_pDOMDoc as an IXMLDOMDocument2 object. (You'll notice the number 2 in this and the namespace is just a byproduct of changes in the C++ MSXML SDK and is not to be confused with the overall MSXML version.)

Most machines with recent Windows operating systems and Internet Explorer will have MSXML 3.0, but yours or your customer's may not. If it does not work, make sure you have msxml3.dll in your System32 folder. The latest MSXML toolkit can be downloaded from MSDN.

Although I had msxml3.dll on my NT box for over a year, I discovered it was not registered properly. My MSXML toolkit download contains xmlinst.exe which I unzipped in C:\TEMP and I did the following from the DOS prompt:

C:\TEMP>xmlinst
 (scanning process table for use of msxml*.dll)
Error while looking for msxml3.dll registry entries!
C:\TEMP>xmlinst -u
 (scanning process table for use of msxml*.dll)
 removed old & new dll entries
C:\TEMP>cd \winnt\system32
C:\WINNT\system32>regsvr32 msxml3.dll
C:\WINNT\system32>cd \temp
C:\TEMP>xmlinst
 (scanning process table for use of msxml*.dll)
 using "%SystemRoot%\system32\msxml3.dll"...
 removed old dll entries
 registered dll for old registry entries.

Update June 11, 2005: I tried compiling the MSXML 3.0 build of CMarkupMSXML on a new machine with VC++ 6.0, and ran into the same compiler errors described in Compiling CMarkupMSXML with MSXML 4.0:

msxml4.tli(49) : error C2143: syntax error : missing ';' before 'tag::id'
msxml4.tli(49) : error C2433: 'DOMNodeType' : 'inline' not permitted on data declarations
msxml4.tli(49) : error C2501: 'DOMNodeType' : missing storage-class or type specifiers
msxml4.tli(49) : fatal error C1004: unexpected end of file found

These errors do not appear if instead of using CMarkupMSXML you only have #import "msxml3.dll" and a limited usage of MSXML code. I have not yet researched into the exact combinations of calls and usages that bring about these errors. There are some postings online discussing this error which they say is due to a difference between MSXML3 file version 8.3 and 8.5 but no solution was given. However, Microsoft Knowledge Base Article 832688 describes what seems to be a relevant problem and gives a solution that works. Simply add the undocumented no_function_mapping compiler directive to your #import statement as follows:

#import <msxml3.dll> no_function_mapping

Skimming the article, it says "the Microsoft Visual C++ compiler inserts the implementation_key compiler directive in the TypeLib Information [TLI file]... to improve performance... and you may receive the compiler errors... This behavior is by design."

So no_function_mapping removes the #pragma implementation_key directives from the TLI file and the compiler errors go away. I am left a little uncertain about two things. First of all, I assume the performance they are speaking of is only for the compiler, not the program runtime. Secondly, labeling it "behavior by design" leaves a lot to be desired. It is not clear whether this is a problem in our case with implementation_key side effects, or the way the compiler "injects" the implementation_key directives, or the way the specific version of MSXML 3.0 leads these directives to be generated.