< 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 deserializing 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 >