April 23, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Working with XML in Managed C++

  • August 23, 2002
  • By Kate Gregory
  • Send Email »
  • More Articles »

From Kate Gregory's Codeguru column, "Using Visual C++ .NET".

In my last column, I showed you how to use MSXML4, the COM component that parses, searches, and generates XML, to work with XML in a "classic Visual C++" application. This time around I'm going to tackle the same tasks, but use the .NET Framework to process XML.

The advantages of using the XML functionality that are built into the .NET class libraries include:

  • Nothing to install, deploy, or redistribute - your apps need the framework anyway, and once you have the framework you have everything you need

  • Simpler code because you're not working with COM - for example you don't need to call CoInitialize() and CoUninitialize().

  • Extra functionality that wasn't in MSXML4.

Sample XML

I'm going to use the same sample XML as I did in the previous column. Here's how it looks:

<?xml version="1.0" encoding="utf-8" ?> 
<PurchaseOrder>
<Customer id="123"/>
<Item SKU="1234" Price="4.56" Quantity="1"/>
<Item SKU="1235" Price="4.58" Quantity="2"/>
</PurchaseOrder>

Loading XML with XmlDocument

The classes for working with XML are in the System::Xml namespace. The XmlDocument represents a DOM document, a tree into which your XML can be loaded. It's the same idea as the DOMDocument you worked with using MSXML4. Here's a simple Managed C++ application that loads a file of XML into memory:

#include "stdafx.h"

#using <mscorlib.dll>
#include <tchar.h>

using namespace System;

#using <System.Xml.dll>
using namespace System::Xml;

// This is the entry point for this application
int _tmain(void)
{

  XmlDocument* xmlDoc = new XmlDocument();

  try
  {
    xmlDoc->Load("sample.xml");
    System::Console::WriteLine("Document loaded ok." );
  }
  catch (Exception *e)
  {
    System::Console::WriteLine("load problem");
    System::Console::WriteLine(e->Message);
  }

  return 0;
}

The #using statement is really important. Without it, you'll get strange compiler errors like 'Xml' : is not a member of 'System' or 'Xml' : a namespace with this name does not exist. When you're working in C# or VB.NET, there's a Project, Add References menu item that takes care of this for you, but as a C++ programmer, you just do it yourself. You can find the assembly to include in the online help for the class or namespace.

Notice also that this code doesn't use a return value from Load() as the COM approach did. The Load() method will throw an exception if it can't load the XML.

Simple arithmetic with the contents of a document

In my last column, I wrote code to flip through all the elements in a document and determine the total price. Here's the equivalent code the .NET way:

xmlDoc->Load("sample.xml");
double total = 0;
System::Console::WriteLine("Document loaded ok." );
XmlNodeList* items = xmlDoc->GetElementsByTagName("Item");
long numitems = items->Count;
for (int i=0;i<numitems;i++)
{
  XmlNode* item = items->Item(i);
  double price =
    Double::Parse(item->Attributes->GetNamedItem("Price")->
                  get_Value());
  double qty =
    Double::Parse(item->Attributes->GetNamedItem("Quantity")->
                  get_Value());
  total += price * qty;
}
System::Console::WriteLine("Purchase Order total is ${0}",
                           __box(total));

I just added this code in the try block. If you're converting an application from COM and MSXML4 to .NET, notice that the capitalization is quite different, and the functions just return the values you need rather than taking a pointer to an object that they change for you. That makes it simpler to chain long strings of calls together as I've done here. Because Managed C++ is a little pickier about types, I've had to use Double::Parse() to change strings to numbers, and to box up total before passing it to WriteLine().

When this application runs, it prints out:

Document loaded ok.
Purchase Order total is $13.72

If you want to dump the XML out, you just need one line of code:

System::Console::WriteLine(xmlDoc->InnerXml);

InnerXml is a String*, so there's no problem passing it to WriteLine() and no need to go through any intermediate variables.





Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel