Share via


Source: validateDOMsmart.cpp

 

[This sample code uses features that were first implemented in MSXML 5.0 for Microsoft Office Applications.]

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>
#include <tchar.h>
#import <msxml6.dll>

// Macro that calls a COM method returning HRESULT value.
#define CHK_HR(stmt)        do{ hr=(stmt); if (FAILED(hr)) goto CleanUp; } while(0)

void dump_com_error(_com_error &e)
{
    _bstr_t bstrSource(e.Source());
    _bstr_t bstrDescription(e.Description());

    printf("Error(dump_com_error)\n");
    printf("\tCode = %08lx\n", e.Error());
    printf("\tCode meaning = %s", e.ErrorMessage());
    printf("\tSource = %s\n", (LPCSTR) bstrSource);
    printf("\tDescription = %s\n", (LPCSTR) bstrDescription);
}

void validateDOMsmart()
{
    MSXML2::IXMLDOMDocument3Ptr         pXMLDoc;
    MSXML2::IXMLDOMDocument2Ptr         pXSDDoc;
    MSXML2::IXMLDOMParseErrorPtr        pError;
    MSXML2::IXMLDOMSchemaCollectionPtr  pSCache;
    MSXML2::IXMLDOMNodePtr              pNode;
    MSXML2::IXMLDOMNodeListPtr          pNodelist;
    HRESULT                             hr = S_OK;

    try
    {
        // Load books.xml into a DOM instance.
        CHK_HR(pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));

        pXMLDoc->async = VARIANT_FALSE;
        pXMLDoc->validateOnParse = VARIANT_FALSE;

        if(pXMLDoc->load(L"books.xml") != VARIANT_TRUE)
        {
            printf("Cannot load books.xml to DOMDocument object.\n");
            CHK_HR(pXMLDoc->parseError->errorCode);
        }

        // Load books.xsd into a DOM instance.
        CHK_HR(pXSDDoc.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));

        pXSDDoc->async = VARIANT_FALSE;
        pXSDDoc->validateOnParse = VARIANT_FALSE;

        if(pXSDDoc->load(L"books.xsd") != VARIANT_TRUE)
        {
            printf("Cannot load books.xsd to DOMDocument object.\n");
            CHK_HR(pXSDDoc->parseError->errorCode);
        }

        // Create a schema cache instance.
        CHK_HR(pSCache.CreateInstance(__uuidof(MSXML2::XMLSchemaCache60), NULL, CLSCTX_INPROC_SERVER));
        // Add the just-loaded schema definition to the schema collection.
        CHK_HR(pSCache->add(L"urn:books", pXSDDoc.GetInterfacePtr()));
        // 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(L"//book");
        printf("Validating all //book nodes, one by one ...\n");
        for (long 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(L"//book/*");
        printf("Validating all children of all book nodes, //book/*, one by one ...\n");
        for (long 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);
    }

CleanUp:
    return;
}

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = CoInitialize(NULL);
    if (SUCCEEDED(hr))
    {
        validateDOMsmart();
        CoUninitialize();
    }
    return 0;

}

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.