< VB .NET XML Serialization Program Example | Main | Another C# XML Serialization Program Example >


 

Chapter 4 Part 13:

Serialization

 

 

What do we have in this chapter 4 Part 13?

  1. Another C++ XML Serialization Program Example

 

 

Another C++ XML Serialization Program Example

 

Create a new CLR console application. You can use the XmlSerializeCP as the project and solution names if you want.

 

Another C++ XML Serialization Program Example - creating a new CLR console application project

 

Add the following code that includes the main().

 

// XmlSerializeCP.cpp : main project file.

// This sample illustrates XML serialization. This sample illustrates using the

// XmlSerializer class. Additionally, this sample illustrates simple

// serialization as well as attribute and overriding serialization. The sample

// illustrates both serialization and deserialization from a file. Note however,

// a serialized file can only be deserialized using the same flags. That is if

// the flag "/override" was specified during serialization, it must also be present

// when deserializing.

//

// Usage:

//      executable_file_name [/serialize | /deserialize]

//                    [/simple | /attribute | /override] [/file file.xml]

//

//          /serialize          Serialize data to XML

//          /deserialize        Deserialize data from XML

//          /simple             Perform simple XML serialization

//          /attribute          Perform XML serialization with attributes

//          /override           Perform XML serialization with overridden attributes

//          /file   filename    File name to serialize to or deserialize from

//

// Sample usage:

//      Simple XML serialization

//          executable_file_name /serialize /simple /file simple.xml

//      Simple XML deserialization

//          executable_file_name /deserialize /simple /file simple.xml

//      Serialize XML with overridden attributes

//          executable_file_name /serialize /override /file override.xml

//      Deserialize XML with overridden attributes

//          executable_file_name /deserialize /override /file override.xml

//

 

#include "stdafx.h"

 

using namespace System;

using namespace System::IO;

using namespace System::Xml::Serialization;

using namespace System::Data;

 

/// <summary>

/// Simple enumeration for the operation to perform: deserialization or serialization.

/// </summary>

enum class SerializeOperation

{

    opRead,                 // Deserialize

    opWrite                  // Serialize

};

 

/// <summary>

/// Enumeration indicating which class to serialize.

/// </summary>

enum class SerializeClass

{

    classSimple,

    classAttribute,

    classOverride

};

 

    /// <summary>

    /// This is a simple helper class which creates a DataSet and initializes some data

    /// within it. The DataSet is an address book with two data columns: name and phone number.

    /// </summary>

    public ref class XmlAddressBookData

    {

        public:

        static DataSet^ CreateAddressBook()

        {

            DataSet^ addressBook;

            DataTable^ friendsTable;

            DataColumn^ infoColumn;

            DataRow^ friendEntry;

 

            // Create a collection, first create the dataset and then the table contained in the dataset

            Console::WriteLine("Creating a collection...");

            addressBook = gcnew DataSet("AddressBook");

            friendsTable = gcnew DataTable("Friends");

 

            // Add columns to the data set

            Console::WriteLine("Adding columns...");

            infoColumn = gcnew DataColumn("Name");

            friendsTable->Columns->Add(infoColumn);

            infoColumn = gcnew DataColumn("Number");

            friendsTable->Columns->Add(infoColumn);

            addressBook->Tables->Add(friendsTable);

 

            // Add a few entries to the collection

            Console::WriteLine("Adding entries...");

            friendEntry = friendsTable->NewRow();

            friendEntry[0] = "Jim";

            friendEntry[1] = "867-5309";

            friendsTable->Rows->Add(friendEntry);

 

            friendEntry = friendsTable->NewRow();

            friendEntry[0] = "Lance";

            friendEntry[1] = "555-4567";

            friendsTable->Rows->Add(friendEntry);

 

            friendEntry = friendsTable->NewRow();

            friendEntry[0] = "Anthony";

            friendEntry[1] = "555-1234";

            friendsTable->Rows->Add(friendEntry);

 

            return addressBook;

        }

 

    /// <summary>

    /// Routine for displaying the contents of the address book.

    /// </summary>

    /// <param name="addressBook">Dataset to print</param>

    public:

        static void PrintAddressBook(DataSet^ addressBook)

        {

             for each (DataTable^ table in addressBook->Tables)

            {

                for each (DataRow^ row in table->Rows)

                {

                    Console::WriteLine("Name {0}: {1}", row["Name"], row["Number"]);

                }

            }

        }

    };

 

/// <summary>

/// Simple data structure to be serialize using the XML formatter. This structure contains a collection.

/// </summary>

public ref class MyXmlSimpleData

{

    public:

    // Preventing the DateTime class from serialization

    // XmlSerializer will skip over it. It is failed to serialize DateTime in C++/CLI

    // Use [XmlIgnore] attribute instead for the XmlSerializer to simply ignore this field.

    [XmlIgnoreAttribute]

    DateTime^     CurrentDate;

    DataSet^      MyAddressBook;

    array<String^>^  DaysOfTheWeek;

 

    // Private properties won't be serialized

    private:

    int         MySalary;

 

    /// <summary>

    /// Default constructor for the MyXmlSimplData class which initializes

    /// the fields and builds a simple collection of names and phone numbers.

    /// </summary>

    public:

    MyXmlSimpleData()

    {

        CurrentDate   = DateTime::Today;

        MySalary      = 0;

        MyAddressBook = XmlAddressBookData::CreateAddressBook();

 

        DaysOfTheWeek = gcnew array<String^>(7);

        DaysOfTheWeek[0] = "Sunday";

        DaysOfTheWeek[1] = "Monday";

        DaysOfTheWeek[2] = "Tuesday";

        DaysOfTheWeek[3] = "Wednesday";

        DaysOfTheWeek[4] = "Thursday";

        DaysOfTheWeek[5] = "Friday";

        DaysOfTheWeek[6] = "Saturday";

    }

 

    /// <summary>

    /// Simple method to set the private fields value.

    /// </summary>

    public:

    void SetSalary(int data)

    {

        MySalary = data;

    }

 

    /// <summary>

    /// Displays the values of all member variables including the collection.

    /// </summary>

    public:

    void Print()

    {

        Console::WriteLine("MyXmlSimpleData::CurrentDate  = {0}", CurrentDate);

        XmlAddressBookData::PrintAddressBook( MyAddressBook );

        Console::WriteLine("MyXmlSimpleData::MySalary     = {0}", MySalary);

 

        for(int i=0; i < DaysOfTheWeek->Length ;i++)

        {

            Console::WriteLine("DaysOfTheWeek[{0}] = {1}", i, DaysOfTheWeek[i]);

        }

    }

 

 

 

 

    /// <summary>

    /// This routine overrides the default serialization by changing the element name

    /// for a member variable when it is serialized. This is typically used when the

    /// same data needs to be serialized to XML with differing XML attributes.

    /// </summary>

    /// <param name="fileStream">The FileStream object to serialize the data to</param>

    public:

    void OverrideSerialization( FileStream^ fileStream )

    {

        XmlElementAttribute^      xmlElementAttribute = gcnew XmlElementAttribute();

        XmlAttributes^                  xmlAttributes = gcnew XmlAttributes();

        XmlAttributeOverrides^   xmlAttributeOverrides = gcnew XmlAttributeOverrides();

        XmlSerializer^                  xmlSerializer = nullptr;

 

        // Override the element name for the "CurrentDate" property

        // Setting XmlIgnore to false overrides the XmlIgnoreAttribute

        // applied to the "CurrentDate" field, thus it will be serialized and vice versa

        xmlElementAttribute->ElementName = "Override_Current_Date";

        xmlAttributes->XmlIgnore = true;

        xmlAttributes->XmlElements->Add( xmlElementAttribute );

        xmlAttributeOverrides->Add( MyXmlSimpleData::typeid, "CurrentDate", xmlAttributes );

 

        // Serialize the class except specify the XmlAttributeOverrides object as well

        xmlSerializer = gcnew XmlSerializer( MyXmlSimpleData::typeid, xmlAttributeOverrides );

 

        try

        {

               Console::WriteLine("Serializing an overridden class...");

               xmlSerializer->Serialize( fileStream, this );

         }

         catch ( InvalidOperationException^ err )

         {

               Console::WriteLine("Serialization of overridden class failed: {0}", err->Message);

         }

    }

};

 

/// <summary>

/// This class illustrates declaring XML attributes along with the class definition.

/// These attributes affect how the data is serialized to XML.

/// </summary>

public ref class MyXmlAttributeData

{

            public:

            // Using Attributes That Control XML Serialization

            // http://msdn.microsoft.com/en-us/library/83y7df3e(VS.71).aspx

            [ XmlElement( ElementName = "_1394Type" )]

            int         FireWireType;

 

            public:

            // Using Attributes That Control XML Serialization

            [ XmlArray( "SupportedDevices" ), XmlArrayItem( "_1394Device" ) ]

            array<String^>^   SupportedDevices;

 

    /// <summary>

    /// Simple constructor to initialize member variables

    /// </summary>

    public:

    MyXmlAttributeData()

    {

        FireWireType = 1;

 

        SupportedDevices = gcnew array<String^>(5);

        SupportedDevices[0] = "scanner";

        SupportedDevices[1] = "camcorder";

        SupportedDevices[2] = "mp3 player";

        SupportedDevices[3] = "IPhone";

        SupportedDevices[4] = "USB drive";

    }

 

    /// <summary>

    /// Prints the class members to the console

    /// </summary>

    public:

    void Print()

    {

        Console::WriteLine("MyXmlAttributeData::FireWireType = {0}", FireWireType);

        for(int i=0; i < SupportedDevices->Length ;i++)

        {

             Console::WriteLine("MyXmlAttributeData::SupportedDevices[{0}] = {1}", i, SupportedDevices[i]);

        }

    }

};

 

/// <summary>

/// This is the class which contains the support routines.

/// </summary>

public ref class XmlSerializeSample

{

    /// <summary>

    /// Displays usage information

    /// </summary>

    public:

    static void usage()

    {

        Console::WriteLine("executable_file_name [/serialize | /deserialize]");

        Console::WriteLine("                     [/simple | /attribute | /override] [/file file.xml]");

        Console::WriteLine("Available options:");

        Console::WriteLine("     /serialize          Serialize data to XML");

        Console::WriteLine("     /deserialize        Deserialize data from XML");

        Console::WriteLine("     /simple             Perform simple XML serialization");

        Console::WriteLine("     /attribute          Perform XML serialization with attributes");

        Console::WriteLine("     /override           Perform XML serialization with overridden attributes");

        Console::WriteLine("     /file   filename    File name to serialize to or deserialize from");

        Console::WriteLine();

    }

 

};

 

/// <summary>

/// Main routine that parses the command line, creates the select file stream, and

/// serializes or deserializes the indicated class.

/// </summary>

/// <param name="args">Command line parameters passed to application</param>

int main(array<System::String ^> ^args)

{

            SerializeOperation serializeOp = SerializeOperation::opWrite;

            SerializeClass serializeClass = SerializeClass::classSimple;

            // A default file name

            String^ fileName = "simpletest.xml";

 

            // Parse the command line

            if(args->Length != 0)

            {

                        for (int i = 0; i < args->Length; i++)

                        {

                                    if (String::Compare(args[i], "/serialize", true) == 0)

                                    {

                                                serializeOp = SerializeOperation::opWrite;

                                    }

                                    else if (String::Compare(args[i], "/deserialize", true) == 0)

                                    {

                                                serializeOp = SerializeOperation::opRead;

                                    }

                                    else if (String::Compare(args[i], "/file", true) == 0)

                                    {

                                                try

                                                {

                                                            fileName = args[++i];

                                                }

                                                catch (IndexOutOfRangeException^)

                                                {

                                                            Console::WriteLine("Please specify output filename!\n");

                                                            XmlSerializeSample::usage();

                                                }

                                    }

                                    else if (String::Compare(args[i], "/simple", true) == 0)

                                    {

                                                serializeClass = SerializeClass::classSimple;

                                    }

                                    else if (String::Compare(args[i], "/attribute", true) == 0)

                                    {

                                                serializeClass = SerializeClass::classAttribute;

                                    }

                                    else if (String::Compare(args[i], "/override", true) == 0)

                                    {

                                                serializeClass = SerializeClass::classOverride;

                                    }

                                    else

                                    {

                                                XmlSerializeSample:: usage();

                                                return 0;

                                    }

                        }

            }

            else

            {

                        XmlSerializeSample:: usage();

                        return 0;

            }

 

            FileStream^ fileStream = nullptr;

            XmlSerializer^ xmlSerializer = nullptr;

 

            try

            {

                        // Create an instance of the FileStream on which serialization or deserialization will take place.

                        if (serializeOp == SerializeOperation::opWrite)

                        {

                                    String^ s = "hello";

                                    array<Byte>^ data = Text::Encoding::ASCII->GetBytes(s->ToCharArray());

                                    fileStream = gcnew FileStream(

                                                fileName,

                                                FileMode::Create,

                                                FileAccess::Write,

                                                FileShare::None

                                                );

                                    fileStream->Write(data, 0, 0);

                                    Console::WriteLine("Writing is OK, filename is " + fileName);

                        }

                        else if (serializeOp == SerializeOperation::opRead)

                        {

                                    fileStream = gcnew FileStream(

                                                fileName,

                                                FileMode::Open,

                                                FileAccess::Read,

                                                FileShare::Read

                                                );

                                    Console::WriteLine("Reading is OK...");

                        }

 

                        if (serializeOp == SerializeOperation::opWrite)

                        {

                                    // If serialization (writing) is selected, we need to create an instance

                                    // of the class which will be serialized to the stream.

                                    if (serializeClass == SerializeClass::classSimple)

                                    {

                                                // Create an instance of the simple class

                                                MyXmlSimpleData^ simpleData = nullptr;

                                                simpleData = gcnew MyXmlSimpleData();

                                                xmlSerializer = gcnew XmlSerializer(MyXmlSimpleData::typeid);

                                               

                                                try

                                                {

                                                            Console::WriteLine("Serializing a simple class...");

                                                            xmlSerializer->Serialize(fileStream, simpleData);

                                                }

                                                catch (InvalidOperationException^ err)

                                                {

                                                            Console::WriteLine("Serialization of simple class failed: {0}", err->Message);

                                                }

                                    }

                                    else if (serializeClass == SerializeClass::classAttribute)

                                    {

                                                // Create an instance of the class containing XML attributes

                                                MyXmlAttributeData^ attributeData = nullptr;

                                                attributeData = gcnew MyXmlAttributeData();

                                                xmlSerializer = gcnew XmlSerializer(MyXmlAttributeData::typeid);

 

                                                try

                                                {

                                                            Console::WriteLine("Serializing an attributed class...");

                                                            xmlSerializer->Serialize(fileStream, attributeData);

                                                }

                                                catch (InvalidOperationException^ err)

                                                {

                                                            Console::WriteLine("Serialization of attributed class failed: {0}", err->Message);

                                                }

                                    }

                                    else if (serializeClass == SerializeClass::classOverride)

                                    {

                                                // Create an instance of the class which has its own override method

                                                // and call that method to serialize the data.

                                                MyXmlSimpleData^ simpleData = nullptr;

                                                simpleData = gcnew MyXmlSimpleData();

                                                simpleData->OverrideSerialization(fileStream);

                                    }

                        }

                        else if (serializeOp == SerializeOperation::opRead)

                        {

                                    // If deserialization (reading) is selected, simply create an instance

                                    // of the XmlSerializer for the type being serialized and call the deserialize method.

                                    if (serializeClass == SerializeClass::classSimple)

                                    {

                                                MyXmlSimpleData^ simpleData = nullptr;

                                                xmlSerializer = gcnew XmlSerializer(MyXmlSimpleData::typeid);

 

                                                try

                                                {

                                                            Console::WriteLine("De-serializing a simple class...");

                                                            simpleData = (MyXmlSimpleData^)xmlSerializer->Deserialize(fileStream);

                                                            simpleData->Print();

                                                }

                                                catch (InvalidOperationException^ err)

                                                {

                                                            Console::WriteLine("Deserialization of simple class failed: {0}", err->Message);

                                                }

                                    }

                                    else if ((serializeClass == SerializeClass::classAttribute) || (serializeClass == SerializeClass::classOverride))

                                    {

                                                MyXmlAttributeData^ attributeData = nullptr;

                                                xmlSerializer = gcnew XmlSerializer(MyXmlAttributeData::typeid);

 

                                                try

                                                {

                                                            Console::WriteLine("De-serializing an overriding/attributed class...");

                                                            attributeData = (MyXmlAttributeData^)xmlSerializer->Deserialize(fileStream);

                                                            attributeData->Print();

                                                }

                                                catch (InvalidOperationException^ err)

                                                {

                                                            Console::WriteLine("Deserialization of overriding/attributed class failed: {0}", err->Message);

                                                }

                                    }

                        }

}

catch(Exception^ err)

{

            Console::WriteLine("Error lor! -->" + err->Message);

}

 

// Close up

try

{

            Console::WriteLine("Closing FileStream...");

            fileStream->Close();

}

catch (Exception^ err)

{

            Console::WriteLine("Error closing FileStream..." + err->Message);

}

return 0;

}

 

Build and run the project.

 

Another C++ XML Serialization Program Example - running the project with default argument values

 

The following are the output samples when the program run at the command prompt.

 

Another C++ XML Serialization Program Example - running the program from command line with argument values

 

Another C++ XML Serialization Program Example - another output sample with argument value of attribute

 

Another C++ XML Serialization Program Example - another output sample with argument value of override

 

Well, we have some error as seen in the above screenshot when de-serializing the overriding and the details is shown below. It is left for your exercise and please take sometime to solve it.

 

 

 

 

Unhandled Exception: System.InvalidOperationException: There is an error in XML document (2, 2). ---> System.InvalidOperationException: <MyXmlSimpleData xmlns=''> was not expected.

   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderMyXmlAttributeData.Read3_MyXmlAttributeData()

   --- End of inner exception stack trace ---

   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)

   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)

   at System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream)

   at main(String[ ] args)

   at mainCRTStartupStrArray(String[ ] arguments)

 

The following is the generated XML file opened in the Internet browser.

 

Another C++ XML Serialization Program Example - the generated XML file used for serialization and de-serialization opened in Internet Browser

 


< VB .NET XML Serialization Program Example | Main | Another C# XML Serialization Program Example >