Xml
People have been shouting that XML is the key to solving system interconnection problems, and the. NET Framework also provides many different class libraries for processing XML data. The XmlDocument class allows you to work with XML data as you do with files, while XmlReader, XmlWriter, and their derived classes enable you to process XML data as data streams. XmlSerializer provides another way to enable you to translate your objects serially and drag into XML. Serialized data allows you to randomly access data as you would a file, while skipping elements that you are not interested in. In this article, I'll show you how to use the XmlSerializer class and how to add attributes to your class to control the serialization process.
XmlSerializer
The XmlSerializer class exists in the System.Xml.dll of the System.Xml.Serialization namespace, which provides serialization services in a highly loosely coupled manner. Your classes do not need to inherit special base classes, and they do not need to implement any special interfaces. Instead, you only need to add custom attributes to your class or to the public domain and read/write properties of those classes. XmlSerializer reads these properties through the opposite map and uses them to map your class and class members to XML elements and attributes.
mapping XML to Objects
Consider the XML statement in table A, which correctly describes the movie that is shown in a movie theater?
Table A
<?xml version= "1.0" encoding= "Utf-8"?>
<theater>
<name>the camelot</name>
<phone> (888) 665-2222</phone>
<movie minutes= "stars=" "2" >
<title>the score</title>
<rating>R</rating>
<showing>16:15:00</showing>
<showing>19:05:00</showing>
<showing>21:40:00</showing>
</movie>
<movie minutes= ">"
<title>Shrek</title>
<rating>PG-13</rating>
<showing>16:00:00</showing>
<showing>19:00:00</showing>
<showing>21:40:00</showing>
</movie>
</theater>
Table B defines a theater (cinema) class that contains the property mappings used by XmlSerializer.
Table B
Using System;
Using System.Xml.Serialization;
Namespace Articles.TechRepublic.XmlSerialization
{
[XmlRoot ("theater")]
public class Theater
{
[XmlElement ("name")]
public string Name = "";
[XmlElement ("Phone")]
public string Phone = "";
[XmlElement ("movie")]
Public movie[] Movies;
public override string ToString ()
{
string movies = "";
if (Movies!= null)
foreach (Movie Movie in Movies)
Movies = "\ n" + movie. ToString ();
Return String.Format ("{0}\n {1}\n{2}"),
Name, Phone, movies);
}
}
The XmlRoot property maps the class theater to the root element theater of the XML. The XmlElement property maps name, phone, and movies data fields to name, phone, and movie XML elements nested within the theater element. Because movies is an movie array, XmlSerializer maps it to multiple XML movie elements.
Table C shows a movie class with attribute mappings
Table C
public class Movie
{
[XmlElement ("title")]
public string Title = "";
[XmlAttribute ("Minutes")]
public uint Minutes = 0;
[XmlElement ("showing", datatype= "Time")]
Public datetime[] showings;
public override string ToString ()
{
string showings = "";
if (showings!= null)
{
showings = "shows at";
foreach (DateTime showing in showings)
showings + = showing. Toshorttimestring () + "";
}
Else
{
showings = "-No showings";
}
Return String.Format ("{0} ({1} min) {2}",
Title, Minutes, showings);
}
}
The XmlElement property maps the title and showings data fields to the title and showing XML elements within the movie element. Like Theater.movie, as a datetime array of movie.showings is mapped to multiple XML showing elements. The properties of the showing data field include positional property arguments datatype= "Time". It maps the datetime value to an XML time value, which removes the date information and retains only the temporal information. The XmlAttribute property maps the Minutes data field to an XML attribute rather than an XML element.
Moviestars (movie star) attributes and Rating (attendance) elements in the XML data are not mapped to anything in the movie class. When drag rows XML data, XmlSerializer simply skips items that it cannot map. When serializing an object, you can add XmlIgnore attributes to the common data field and to the properties you want XmlSerializer to skip.
XmlRoot, XmlElement, and XmlAttribute attribute classes should include the suffix "attribute." In my property statement, I use an abbreviated form with no suffix. Public properties in the theater and movie classes can be rewritten as public properties to achieve better encapsulation. XmlSerializer can use them in the same way. I use them here as data fields to make the code more compact.
Drag XML data into objects
Loading XML data into a theater object has become very easy now. The program in table D, Xmlin, creates a theater object through drag movie showings XML data. This program executes through the command line, and you need to specify an input XML file.
Table D
Using System;
Using System.Xml.Serialization;
Using System.IO;
Using Articles.TechRepublic.XmlSerialization;
public class Xmlin
{
public static void Main (string[] args)
{
if (args. Length!= 1)
{
Console.WriteLine ("Usage:xmlin infile.xml");
Return
}
Try
{
Deserialize the specified file to a theater object.
XmlSerializer xs = new XmlSerializer (typeof (Theater));
FileStream fs = new FileStream (args[0], FileMode.Open);
Theater Theater = (theater) xs. Deserialize (FS);
Display the Theater object.
Console.WriteLine (theater);
}
catch (Exception x)
{
Console.WriteLine ("Exception:" + x.message);
}
}
}
Output:
>xmlin Theaterin.xml
The Camelot
(888) # 665-2222
The Score (min) shows at 4:15 pm 7:05 pm 9:40 pm
Shrek (min) shows at 4:00 pm 7:00 pm 9:40 pm
The main program code is placed in the Try Code section of the main function. You first create a XmlSerializer object and indicate a System.Type object to tell the type of object that the drag is creating. The typeof operator returns a System.Type object for the theater class. Then, open a file stream to read the input XML file. Call the XmlSerializer deserialize method and pass the file to it. Deserialize returns a reference to the theater object. The ToString method in theater and movie objects allows you to simply output them.
Serializing an object into XML
It is also easy to generate XML data from a theater object. The program in table E, Xmlout, is the serialization of a theater object into an XML file. This program executes through the command line, and you need to indicate the output XML file.
Table E
Using System;
Using System.Xml;
Using System.Xml.Serialization;
Using System.IO;
Using Articles.TechRepublic.XmlSerialization;
public class Xmlout
{
Returns a populated theater object.
public static theater Gettheater ()
{
Movie Movie = new Movie ();
Movie. Title = "O Brother, where Art Thou?";
Movie. Minutes = 102;
Movie. showings = new Datetime[3];
Movie. Showings[0] = new DateTime (2001, 8, 2, 13, 15, 0);
Movie. SHOWINGS[1] = new DateTime (2001, 8, 2, 16, 30, 0);
Movie. SHOWINGS[2] = new DateTime (2001, 8, 2, 19, 55, 0);
Theater Theater = new Theater ();
Theater. Name = "Hollywood Movies 10";
Theater. Phone = "(972) 555-154";
Theater. Movies = new Movie[1];
Theater. Movies[0] = movie;
return theater;
}
public static void Main (string[] args)
{
if (args. Length!= 1)
{
Console.WriteLine ("Usage:xmlout outfile.xml");
Return
}
Try
{
Theater Theater = Gettheater ();
Serialize the theater object to an XML file.
XmlSerializer xs = new XmlSerializer (typeof (Theater));
FileStream fs = new FileStream (args[0], filemode.create);
Xs. Serialize (FS, theater);
}
catch (Exception x)
{
Console.WriteLine ("Exception:" + x.message);
}
}
}
Invocation:
>xmlout Theaterout.xml
Theaterout.xml Contents:
<?xml version= "1.0"?>
<theater
Xmlns:xsi=http://www.w3.org/2001/xmlschema-instance
xmlns:xsd= "Http://www.w3.org/2001/XMLSchema" >
<name>hollywood Movies 10</name>
<phone> (972) 555-154</phone>
<movie minutes= "102" >
<title>o Brother, where Art thou?</title>
<showing>13:15:00.0000000-06:00</showing>
<showing>16:30:00.0000000-06:00</showing>
<showing>19:55:00.0000000-06:00</showing>
</movie>
</theater>
The main program code is placed in the Try Code section of the main function. First, you create a theater object by using the Gettheater help function. Then, open a file stream to generate the output XML file. Invokes the XmlSerializer serialize method and passes it to the file stream and theater object. That's it. Simple--xml file Generation!
The theater element of the output contains the XML namespace attributes (xmlns) that are generated for the template and template instance namespaces, although the data does not represent anything in these two namespaces. The -06:00 in the showing element refers to the central United States time, or the GMT time minus an hour, which is my time zone.
Moving data is a piece of cake.
XmlSerializer makes it easy to move data between objects and XML, as long as you add XML mapping attributes to the class. But for more complex object models, creating XML maps manually can become cumbersome and error-prone. In my next article, I'll show you how to automate this work and implement tighter control over your XML data.