分享

MSXML 4.0 DOM API

 昵称11247 2006-11-23
Microsoft XML Core Services

Summary
This sample application illustrates the MSXML 4.0 DOM API. This is a Visual C++ 6.0 Win32 console application that uses MSXML 4.0 to load a remote or local XML document, adds an attribute to the document‘s root element; then uses XPath to search for a node, if found, updates the node‘s value with the current datetime, else creates a new node and sets its value.


Steps
Steps that we followed to create this application:
1. Start Visual C++ 6.0 and create a new Win32 Console Application project.
2. Add the following lines in the stdafx.h:
#include <TCHAR.H>
                        #include <stdio.h>
                        #include <time.h>
                        #import "msxml4.dll"
                        //      ^^^^^^^^^^^^
                        // If this import statement fails, you need to install MSXML 4.0 SP1 from:
                        //
                        // http://msdn.microsoft.com/downloads/sample.asp?url=/MSDN-FILES/027/001/766/msdncompositedoc.xml
                        #include <msxml2.h>
                        //       ^^^^^^^^^^
                        // If this include statement fails, you need to install MSXML 4.0 SP1 SDK from:
                        //
                        // http://msdn.microsoft.com/downloads/sample.asp?url=/MSDN-FILES/027/001/766/msdncompositedoc.xml
                        //
                        // You also need to add the include file and library search path
                        // to Visual C++‘s list of directories (Tools > Options... > Directories).
                        using namespace MSXML2;
                        inline void EVAL_HR( HRESULT _hr )
                        { if FAILED(_hr) throw(_hr); }
                        
3. The above lines import the MSXML 4 type library, include the MSXML header file, and contain a tiny utility function to check the HRESULT value.
4. The main function looks like as below:
int main(int argc, char* argv[])
                        {
                        try
                        {
                        EVAL_HR(CoInitialize(NULL));
                        //	Make sure MSXML 4.0 is installed
                        if (!isMSXMLInstalled())
                        return -1;
                        IXMLDOMDocument2Ptr pXMLDoc = NULL;
                        TCHAR	szHTTPURL[MAX_PATH] = {0};
                        _tcscpy(szHTTPURL, g_szHTTPURL);
                        _tcscat(szHTTPURL, g_szISBN);
                        //	Load the XML document
                        if (loadDocument(pXMLDoc, szHTTPURL, true))
                        {
                        //	Add an attribute and an element
                        updateDocument(pXMLDoc);
                        //	Save the updated document as a local XML file
                        pXMLDoc->save(g_szLocalFile);
                        }
                        else
                        {//	Load Failed
                        printMSXMLError(pXMLDoc);
                        }
                        }
                        catch(...)
                        {//	Exception handling
                        }
                        CoUninitialize();
                        return 0;
                        }
5. You‘ll notice that the main function simply calls some utility functions to load the XML document, update it and print an error if the document fails to load. These functions are declared and defined in a header file called Utils.h. Let‘s look at each function individually.
6. Let‘s first look at a function that makes sure that MSXML 4.0 is installed:
bool isMSXMLInstalled()
                        {
                        try
                        {
                        HKEY hKey;
                        DWORD retCode;
                        retCode = RegOpenKeyEx(HKEY_CLASSES_ROOT,
                        _T("CLSID\\{88d969c0-f192-11d4-a65f-0040963251e5}\\InProcServer32"),
                        0,
                        KEY_QUERY_VALUE,
                        &hKey);
                        if (retCode != ERROR_SUCCESS) return false;
                        retCode = RegQueryValueEx(hKey, _T(""), NULL, NULL,
                        (LPBYTE)szTemp, &(dwLen = sizeof(szTemp)));
                        if (retCode != ERROR_SUCCESS) return false;
                        RegCloseKey(hKey);
                        double dVer;
                        int i;
                        for (i = _tcslen(szTemp); i >= 0; --i)
                        {
                        if (szTemp[i] == _T(‘\\‘))
                        break;
                        }
                        if (_stscanf(szTemp + i + 1, _T("msxml%lf"), &dVer) == 0 || dVer < 4.0)
                        {
                        _ftprintf(stderr, _T("\nError: MSXML 4.0 is not installed. Exiting.\n"));
                        return false;
                        }
                        else
                        {
                        return true;
                        }
                        }
                        catch(...)
                        {//	Exception handling
                        }
                        return false;
                        }
7. The above function simply uses the MSXML 4.0 DOMDocument (Msxml2.DOMDocument.4.0) CLSID to search the corresponding COM DLL in the registry. If it is MSXML4.dll, the method returns true, else it returns false.
8. The next function in the Utils.h is loadDocument. It creates MSXML DOMDocument instance using the version dependent ProgID and then loads the document. The method initializes the first parameter (pXMLDoc), and returns True or False based on if the document was successfully loaded or not.
_variant_t loadDocument(IXMLDOMDocument2Ptr& pXMLDoc, LPCTSTR szDocURL, bool bOverHTTP)
                        {
                        _variant_t varLoadResult((bool)FALSE);
                        try
                        {
                        //	Create MSXML DOM object
                        EVAL_HR(pXMLDoc.CreateInstance("Msxml2.DOMDocument.4.0"));
                        //	Load the document synchronously
                        pXMLDoc->async = false;
                        if (bOverHTTP)
                        {
                        //	If loading the document over HTTP (see KB Q321125 for details)
                        pXMLDoc->setProperty("ServerHTTPRequest", VARIANT_TRUE);
                        }
                        //	Load the XML document
                        varLoadResult = pXMLDoc->load(szDocURL);
                        }
                        catch(...)
                        {//Exception handling
                        }
                        return varLoadResult;
                        }
9. Once the XML document is loaded in the DOM tree, the following function is used to add an attribute to the root element, and update/add an element under the root element.
void updateDocument(IXMLDOMDocument2Ptr& pXMLDoc)
                        {
                        try
                        {
                        IXMLDOMNodePtr pLastSavedNode = NULL;
                        IXMLDOMElementPtr pRootElem = NULL;
                        //	Get root element
                        EVAL_HR(pXMLDoc->get_documentElement(&pRootElem));
                        //	Add the ISBN attribute to the root element
                        pRootElem->setAttribute("ISBN", g_szISBN);
                        //	See KB Article Q313372 for details on
                        //	default namespace and XPath expression evaluation
                        TCHAR szTemp[MAX_PATH] = "xmlns:defNS=‘";
                        //	Get the default namespace on the root element
                        _bstr_t bstrNamespaceURI =  pRootElem->namespaceURI;
                        _tcscat(szTemp, bstrNamespaceURI);
                        _tcscat(szTemp, "‘");
                        pXMLDoc->setProperty("SelectionNamespaces", szTemp);
                        //	The XPath expression
                        _tcscpy(szTemp, "//defNS:");
                        _tcscat(szTemp, g_szNode);
                        //	See if the "LastSaved" element exists
                        pLastSavedNode = pRootElem->selectSingleNode(_bstr_t(szTemp));
                        if(pLastSavedNode == NULL)
                        {//	Element not found!
                        _variant_t varNodeType((short)MSXML2::NODE_ELEMENT);
                        //	create the LastSaved node
                        pLastSavedNode = pXMLDoc->createNode(varNodeType, g_szNode, bstrNamespaceURI);
                        //	append this new node under the document root element
                        pRootElem->appendChild(pLastSavedNode);
                        }
                        //	Get current Date and Time
                        time_t timCurDate;
                        time (&timCurDate);
                        //	And set it‘s value to current date and time
                        pLastSavedNode->nodeTypedValue = ctime (&timCurDate);
                        }
                        catch(...)
                        {//Exception Handling
                        }
                        }
10. The above method first gets the document‘s root element. It then adds/updates the ISBN attribute on the root node.

Then we use the XPath expression and selectSingleNode method to see if the node named LastSaved already exists as a child of the root element. If found, we just update its value, else we create a new node and attach it as a child to the root element.

When creating the new node (by calling createNode), we make sure to give the same namespace as the default namespace on the root element, so that the newly created node does not contain a blank namespace declaration, and in fact belongs to the document‘s default namespace.
11. The final utility function, printMSXMLError, simply uses the IXMLDOMParseError interface to print some error information on the stderr stream:
void printMSXMLError(const IXMLDOMDocument2Ptr& pXMLDoc)
                        {
                        try
                        {
                        //	Get parseError interface
                        IXMLDOMParseErrorPtr pError = NULL;
                        EVAL_HR(pXMLDoc->get_parseError(&pError));
                        _ftprintf(stderr, pError->reason);
                        }
                        catch(...)
                        {//Exception handling
                        }
                        }
12. The code uses some global variables defined in another header file named GlobalDefs.h:
LPCTSTR	g_szHTTPURL	=
                        _T("http://www.PerfectXML.net/WebServices/SalesRankNPrice/BookService.asmx/GetAll?ISBN=");
                        LPCTSTR	g_szISBN		= _T("0072223693");
                        //	Uncomment following two lines in case not connected to the internet
                        //LPCTSTR g_szHTTPURL		= _T("c:\\SalesRankNPrice.xml");
                        //LPCTSTR	g_szISBN		= _T("");
                        LPCTSTR g_szLocalFile	= _T("c:\\SalesRankNPrice.xml");
                        LPCTSTR g_szNode		= _T("LastSaved");
                        #define TEMP_SIZE  _MAX_PATH               // size of short buffer
                        static _TCHAR   szTemp[TEMP_SIZE];         // multipurpose buffer on stack
                        static DWORD    dwLen;                     // buffer size



Here is the text from the ReadMe.TXT file included with the code download for this sample application:
========================================================================
                        CONSOLE APPLICATION : MSXML4DOM
                        ========================================================================
                        MSXML4DOM.cpp
                        Sample code to illustrate using MSXML 4.0 (SP1) basic DOM
                        (Document Object Model) features in C++.
                        This application creates
                        a.) loads an XML document from an HTTP location
                        (
                        actually, sends a HTTP GET request to a
                        Web service (SalesRankNPrice) method.
                        )
                        b.) Modifies that document
                        (
                        creates the element named LastSaved
                        under the root element, and sets its value
                        to current date and time.
                        Also adds the ISBN attribute to the root element
                        )
                        c.) Saves the updated document on the local hard disk
                        After the program finishes, open the C:\SalesRankNPrice.xml (g_szLocalFile)
                        file using Internet Explorer to see the results.
                        --------------------------------------------------------------
                        Copyright (C) 2002 http://www.PerfectXML.com
                        Created: July 10, 2002
                        Author: PerfectXML.com Team (msxml@PerfectXML.com)
                        See http://www.PerfectXML.com/CPPMSXML/20020710.asp for details.
                        /////////////////////////////////////////////////////////////////////////////

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多