Microsoft XML Core Services (MSXML) 5.0 for Microsoft Office - DOM Developer's Guide

Source: validateDOMsmart.cpp

The source code performs the following basic steps:

  1. Creates a DOM instance (pXMLDoc) to hold the XML data.
  2. Creates a DOM instance (pXSDDoc) to hold the XML Schema definition.
  3. Creates an IXMLSchemaCollection or IXMLSchemaCollection2 object (pSCache). This object is also called a schema cache. The application then adds the XML Schema definition (pXSDDoc) to the pSCache.
  4. Associates pSCache with the schemas property of the DOM object for the XML data (pXMLDoc).
  5. Calls the following validation methods on the DOM object for XML data (pXMLDoc):
    • Calls the validate method on pXMLDoc to validate the data set as a whole, and/or
    • Calls the validateNode(pNode) method on pXMLDoc to validate a node object (pNode) selected from pXMLDoc.

Checks the error returned from validate method and/or the validateNode(pNode) method, to determine if the specified XML data set is valid against the given XML Schema definition.

C/C++ Source File (validateDOMsmart.cpp)

#include <stdio.h>
#import <msxml5.dll>
using namespace MSXML2;

void dump_com_error(_com_error &e);

int main(int argc, char* argv[])
{
   IXMLDOMDocument3Ptr            pXMLDoc  = NULL;
   IXMLDOMDocument3Ptr            pXSDDoc  = NULL;
   IXMLDOMParseErrorPtr           pError   = NULL;
   IXMLDOMSchemaCollectionPtr     pSCache  = NULL;
   IXMLDOMNodePtr                 pNode    = NULL;
   IXMLDOMNodeListPtr             pNodelist= NULL;
   HRESULT                        hr;

   CoInitialize(NULL);
   try{
     // Load books.xml into a DOM instance.
      hr = pXMLDoc.CreateInstance(__uuidof(DOMDocument50));
      if (FAILED(hr)) {
        printf( "Cannot create DOMDocument50 instance for XMLDoc\n");
         return 0;
     }
      pXMLDoc->async           =  VARIANT_FALSE;       
      pXMLDoc->validateOnParse =  VARIANT_FALSE;
      if(pXMLDoc->load("books.xml") != VARIANT_TRUE)
      {
           printf( "Cannot load books.xml to XMLDoc object\n");
          return 0;
      }

     // Load books.xsd into a DOM instance.
      hr = pXSDDoc.CreateInstance(__uuidof(DOMDocument50));
      if (FAILED(hr)) {
        printf( "Cannot create DOMDocument50 instance for XSDDoc\n");
         return 0;
     }
      pXSDDoc->async           =  VARIANT_FALSE;       
      pXSDDoc->validateOnParse =  VARIANT_FALSE;
      if(pXSDDoc->load("books.xsd") != VARIANT_TRUE)
      {
           printf( "Cannot load books.xsd to XSDDoc object\n");
          return 0;
      }

      // Create a schema cache instance.
     hr = pSCache.CreateInstance(__uuidof(XMLSchemaCache50));
      if (FAILED(hr)) {
        printf( "Cannot create XMLSchemaCache50 instance in pSCache\n");
         return 0;
     }

     // Add the just-loaded schema definition to the schema collection.
     hr = pSCache->add("urn:books", pXSDDoc.GetInterfacePtr());
      if (FAILED(hr)) {
        printf("Cannot add schema\n");
         return 0;
     }

     // Associate the schema collection with the XMLDoc instance. 
      pXMLDoc->schemas = pSCache.GetInterfacePtr();
     
     // Validate the entire DOM.
     printf("Validating DOM...\n");

      pError =pXMLDoc->validate();
      if (pError->errorCode != 0)
        printf("\tXMLDoc is not valid because\n%s\n", 
(LPCSTR)pError->Getreason());
      else
         printf("\tXMLDoc is validated: \n%s\n", (LPCSTR)pXMLDoc->xml);
     
     // Validate all //book nodes, node-by-node.
      pNodelist = pXMLDoc->selectNodes("//book");     
     printf("Validating all //book nodes, one by one ...\n");
     for (int i=0; i<pNodelist->length; i++) 
     {
        pNode = pNodelist->item[i];
        pError = pXMLDoc->validateNode(pNode);
        if (pError->errorCode != 0)
          printf("\t<%s> (%d) is not valid because\n%s\n",
            (LPCSTR)pNode->nodeName, i, 
            (LPCSTR)pError->Getreason());
         else
          printf("\t<%s> (%d) is a valid node\n", (LPCSTR)pNode->nodeName, i);
     }

     // Validate all children of all book nodes, //book/*, node-by-node.
     pNodelist = pXMLDoc->selectNodes("//book/*");     
     printf("Validating all children of all book nodes, //book/*, one by one ...\n");
     for (i=0; i<pNodelist->length; i++) 
     {
        pNode = pNodelist->item[i];
        pError = pXMLDoc->validateNode(pNode);
        if (pError->errorCode != 0)
          printf("\t<%s> (%d) is not valid because\n%s\n",
            (LPCSTR)pNode->nodeName, i, 
            (LPCSTR)pError->Getreason());
         else
          printf("\t<%s> (%d) is a valid node\n", 
(LPCSTR)pNode->nodeName, i);
     }
    }
   catch(_com_error &e)
   {
      dump_com_error(e);
   }
   pXMLDoc.Release();
   pXSDDoc.Release();
   pError.Release();
   pSCache.Release();
   pNode.Release();
   pNodelist.Release();
   CoUninitialize();
   return 0;
}


void dump_com_error(_com_error &e)
{
   printf("Error(dump_com_error)\n");
   printf("\tCode = %08lx\n", e.Error());
   printf("\tCode meaning = %s", e.ErrorMessage());
   _bstr_t bstrSource(e.Source());
   _bstr_t bstrDescription(e.Description());
   printf("\tSource = %s\n", (LPCSTR) bstrSource);
   printf("\tDescription = %s\n", (LPCSTR) bstrDescription);
}

To add the validateDOMsmart source code to the project

  1. Create a new C++ source file. For detailed instructions on how to do this, see Set Up My Visual C++ Project. Name the new file validateDOMsmart.cpp.
  2. Copy the C/C++ source code above, and paste it into the source file you just created.

Next, we'll add the resource files to the validateDOMsmart project.