MSXML in C++ but as elegant as in C# (Part 2)

22 בדצמבר 2008

תגיות: ,
אין תגובות

So, in my opening post on this subject (Part 1), I promised to show you some useful sample code using MSXML, written in C++ yet as elegant as C#.

Well. Here is an example of what can be achieved.

C++ C#

#include "stdafx.h"

inline void IndentedPrint (int indent, char* format, …)

{

    char m_Message[512];

    va_list args;

    va_start(args, format);

    vsprintf_s(m_Message, format, args);

    va_end(args);

    printf ("%*s%s", indent, "\t", m_Message);

}

 

void DisplayAttribute (XmlNode node, int depth)

{

    IndentedPrint (depth, "type: %s name: %s value: %s \n",

        NodeTypeString (node->nodeType),

        (const char*) node->nodeName,

        (const char*) (_bstr_t) node->nodeValue);

}

void DisplayNode (XmlNode node, int depth = 0);

void DisplayNodes (XmlNodeList nodes, int depth)

{

    for (int i=0; i<nodes->length; i++)

    {

        DisplayNode (nodes->item[i], depth);

    }

}

void DisplayNode (XmlNode node, int depth)

{

    IndentedPrint (depth, "type: %s name: %s",

        NodeTypeString (node->nodeType),

        (const char*) node->nodeName);

 

    if (node->nodeType == MSXML2::NODE_TEXT)

    {

        IndentedPrint (0, "text: %s\n",

            (const char*) (_bstr_t) node->nodeValue);

    }

    else

    {

        printf ("\n");

 

        XmlNamedNodeMap attrMap = node->attributes;

        if (attrMap)

        {

            for (int i=0; i<attrMap->length; i++)

            {

                DisplayAttribute (

                    attrMap->item[i], depth);

            }

            IndentedPrint (depth, "\n");

        }

 

        XmlNodeList childNodes = node->childNodes;

        if (childNodes)

            DisplayNodes (childNodes, depth + 5);

    }

}

void DisplayXPath (char* xmlFileName, char* xpath)

{

    XmlDocument xmlDoc (CLSID_DOMDocument60);

 

    VARIANT_BOOL ok = xmlDoc->load(xmlFileName);

    if (! ok)

        throw Error ("Failed to load %s", xmlFileName);

 

    printf ("Entire document\n");

 

    DisplayNode (xmlDoc->documentElement, 5);

 

    printf ("Nodes in %s\n", xpath);

 

    XmlNodeList nodeList = xmlDoc->selectNodes(xpath);

 

    DisplayNodes (nodeList, 5);

}

void main(int argc, char* argv[])

{

    ComInit com;

    try

    {

        DisplayXPath ("books.xml", "//@*");

    }

    catch (Error e)

    {

        printf (e);

    }

    catch (_com_error e)

    {

        printf (e.ErrorMessage());

    }

    printf ("\nDone\n");

    _getch ();

}

using System;

using System.Xml;

class Program

{

    void IndentedPrint (int indent, string format, params object[] array)

    {

        string indentedString = "".PadLeft(indent);

        Console.WriteLine(indentedString + format, array);

    }

 

    void DisplayAttribute (XmlNode node, int depth)

    {

        IndentedPrint (depth, "type: {0} name: {1} value: {2} \n",

            node.NodeType.ToString(),

            node.Name,

            node.Value);

    }

 

    void DisplayNodes (XmlNodeList nodes, int depth)

    {

        for (int i=0; i<nodes.Count; i++)

        {

            DisplayNode (nodes[i], depth);

        }

    }

 

    void DisplayNode (XmlNode node, int depth)

    {

        IndentedPrint (depth, "type: {0} name: {1}",

            node.NodeType.ToString(),

            node.Name);

 

        if (node.NodeType == XmlNodeType.Text)

        {

            IndentedPrint (0, "text: {0}\n",

                node.Value);

        }

        else

        {

            Console.WriteLine();

            XmlNamedNodeMap attrMap = node.Attributes;

            if (attrMap != null)

            {

                for (int i=0; i<attrMap.Count; i++)

                {

                    DisplayAttribute (

                        attrMap.Item(i), depth);

                }

                IndentedPrint (depth, "\n");

            }

            XmlNodeList childNodes = node.ChildNodes;

            if (childNodes != null)

                DisplayNodes (childNodes, depth + 5);

        }

    }

 

    void DisplayXPath (string xmlFileName, string xpath)

    {

        XmlDocument xmlDoc = new XmlDocument();

 

        xmlDoc.Load(xmlFileName);

 

        Console.WriteLine("Entire document\n");

 

        DisplayNode (xmlDoc.DocumentElement, 5);

 

        Console.WriteLine("Nodes in {0}\n", xpath);

 

        XmlNodeList nodeList = xmlDoc.SelectNodes(xpath);

 

        DisplayNodes (nodeList, 5);

    }

 

    static void Main(string[] args)

    {

        try

        {

            string xmlFileName = @"..\..\Samples\books.xml";

            new Program().DisplayXPath(xmlFileName, "//@*");

        }

        catch (Exception e)

        {

            Console.WriteLine(e.Message);

        }

        Console.WriteLine("\nDone\n");

        Console.ReadLine();

    }

}

The code on the left is written in C++ using MSXML6, the code on the right in C# using the System.Xml namespace.

Both snippets perform the same task: Loading an xml file as a DOM object and displaying its nodes recursively. I threw in a bit of XPath too.

Very similar no?

This is the code for this project pair (DOMAndXPathCpp and DOMAndXPathCs) along with 4 others.

In my next posts (next is Part 3) I will explain each project pair and how I did away with all those QueryInterfaces, Releases and HRESULTS.

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *