Windows Systems Programming: Spring 2004

[ Home | Syllabus | Course Notes | Assignments | Search]


Dealing with XML in C++ (Before .NET)

This program is like the ones I used to teach in this course - its uses the COM (Component Object Model) developed my microsoft and it lacks many of the functions available in the FCL that make XML processing so much easier.

It makes you appreciate how much better a toolkit .NET provides

 

#include <stdio.h>
#include <windows.h>

void ShowGuitarType (IXMLDOMNode* pNode);
BOOL GetChildElementByTagName (LPOLESTR pName, IXMLDOMNode* pParent,
    IXMLDOMNode** ppNode);
BOOL IsElementNamed (LPOLESTR pName, IXMLDOMNode* pNode);

int main (int argc, char* argv[])
{
    HRESULT hr = CoInitialize (NULL); 

    // Instantiate the MS XML parser
    IXMLDOMDocument* pDoc;
    hr = CoCreateInstance (CLSID_DOMDocument, NULL,
        CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**) &pDoc);

    if (SUCCEEDED (hr)) {
        // Load Guitars.xml
        VARIANT_BOOL success;
        BSTR file = SysAllocString (OLESTR ("Guitars.xml"));
        VARIANT var;
        var.vt = VT_BSTR;
        var.bstrVal = file;

        pDoc->put_async (VARIANT_FALSE);
        hr = pDoc->load (var, &success);
        SysFreeString (file);

        if (SUCCEEDED (hr) && hr != S_FALSE) {
            // Get a list of elements named "Guitar"
            IXMLDOMNodeList* pNodeList;
            BSTR tag = SysAllocString (OLESTR ("Guitar"));
            hr = pDoc->getElementsByTagName (tag, &pNodeList);
            SysFreeString (tag);

            if (SUCCEEDED (hr)) {
                // Get a count of the elements returned
                long count;
                hr = pNodeList->get_length (&count);

                if (SUCCEEDED (hr)) {
                    pNodeList->reset ();

                    // Walk the list element by element
                    for (int i=0; i<count; i++) {
                        IXMLDOMNode* pNode;
                        hr = pNodeList->get_item (i, &pNode);

                        if (SUCCEEDED (hr)) {
                            // Show the Make and Model subelements
                            ShowGuitarType (pNode);
                            pNode->Release ();
                        }
                    }
                }
                pNodeList->Release ();
            }
        }
        pDoc->Release ();
    }

    CoUninitialize ();
    return 0;
}

void ShowGuitarType (IXMLDOMNode* pNode)
{
    IXMLDOMNode* pMakeNode;
    IXMLDOMNode* pModelNode;

    // Get an IXMLDOMNode pointer to the Make subelement
    if (GetChildElementByTagName (OLESTR ("Make"), pNode,
        &pMakeNode)) {
        // Get the Make subelement's text
        BSTR make;
        HRESULT hr = pMakeNode->get_text (&make);

        if (SUCCEEDED (hr) && hr != S_FALSE) {
            // Get an IXMLDOMNode pointer to the Model subelement
            if (GetChildElementByTagName (OLESTR ("Model"), pNode,
                &pModelNode)) {
                // Get the Model subelement's text
                BSTR model;
                hr = pModelNode->get_text (&model);

                if (SUCCEEDED (hr) && hr != S_FALSE) {
                    // Output the guitar's make and model
                    wprintf (OLESTR ("%s %s\n"), make, model);
                    SysFreeString (model);
                }
                pModelNode->Release ();
            }
            SysFreeString (make);
        }
        pMakeNode->Release ();
    }
}

BOOL GetChildElementByTagName (LPOLESTR pName, IXMLDOMNode* pParent,
    IXMLDOMNode** ppNode)
{
    // Get a list of nodes that are children of pParent
    IXMLDOMNodeList* pNodeList;
    HRESULT hr = pParent->get_childNodes (&pNodeList);

    if (SUCCEEDED (hr)) {
        // Get a count of the nodes returned
        long count;
        hr = pNodeList->get_length (&count);

        if (SUCCEEDED (hr)) {
            pNodeList->reset ();

            // Walk the list node by node
            for (int i=0; i<count; i++) {
                IXMLDOMNode* pNode;
                hr = pNodeList->get_item (i, &pNode);

                if (SUCCEEDED (hr)) {
                    // If the node is an element whose name matches
                    // the input name, return an IXMLDOMNode pointer
                    if (IsElementNamed (pName, pNode)) {
                        *ppNode = pNode;
                        pNodeList->Release ();
                        return TRUE;
                    }
                    pNode->Release ();
                }
            }
        }
        pNodeList->Release ();
    }

    return FALSE;
}

BOOL IsElementNamed (LPOLESTR pName, IXMLDOMNode* pNode)
{
    BOOL retval;

    // Get the node type
    DOMNodeType type;
    HRESULT hr = pNode->get_nodeType (&type);

    if (SUCCEEDED (hr) && type == NODE_ELEMENT) {
        // If the node is an element, get its name
        BSTR name;
        hr = pNode->get_nodeName (&name);

        if (SUCCEEDED (hr)) {
            // If the element name matches the input name, return
            // TRUE to indicate a match
            retval = (wcscmp (name, pName) == 0) ? TRUE : FALSE;
            SysFreeString (name);
        }
    }

    return retval;
}


Here is the equivalent program in C#

using System;
using System.Xml;

class MyApp
{
    static void Main ()
    {
        XmlDocument doc = new XmlDocument ();
        doc.Load ("Guitars.xml");
        XmlNodeList nodes = doc.GetElementsByTagName ("Guitar");
        foreach (XmlNode node in nodes) {
            Console.WriteLine ("{0} {1}", node["Make"].InnerText,
                node["Model"].InnerText);
        }
    }
}
 

 

 


Copyright chris wild 1999-2004.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: March 29, 2004.