Mark Wilson I am the creator of TopXML. I am available for international and local (Australia) contracts. I am a Solution Architect/Business Analyst. I have worked in IT in several countries (NZ, Australia, South Africa, UK) building and training teams for government and very large non-governmental organizations. I am ex-Microsoft Consulting Services. I wrote the first book on Microsoft XML published in 2000 called XML Programming with VB and ASP. Most recently I have been building tools for the SEO industry. Ask me for a 37 point SEO health-checkup for your website.
In the previous section we learned how to save and restore an
object with the XmlSerializer, yet we haven’t actually looked at the output
of the Serialize() method. We set out to write a class to obtain an XML
representation that would match the car element in the XML document; the generated XML was supposed to contain a car element with
attributes for make, model and year of the car. Now let’s compare the output of
the XmlSerializer to the earlier format. The following listing shows the
two side-by-side.
XML format From Earlier
XML created by the
XmlSerializer
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<car
<Car …>
make="Ford"
<Make>Ford</Make>
model="Explorer"
<Model>Explorer</Model>
year="1997"
<Year>1997</Year>
/>
</Car>
Close, but no cigar! All the data encapsulated by the Car object
is present in the XML document, yet the structure is not quite what needed. The
output document starts with a Car element following the name of the class of the serialized
object. All fields of the class are represented as elements in the generated
XML document, but we really wanted them to be attributes. What would we do if
we had to send XML to a receiver who can only process the data in attributes?
Could we still serialize with the XmlSerializer? Yes, absolutely. In fact that
is what the XmlSerializer was designed for: map classes to arbitrary XML
formats.
During the introduction of this chapter we mentioned the
important role .NET metadata attributes are playing in XML serialization. Now
we will get to know the specific attributes that control how classes are mapped
to XML types and we will learn applying them, too. Table 9.3 lists the XML
serialization attributes available in System.Runtime.Serialization namespace of the .NET
framework
Table 9.3 XML Serialization Attributes control Class-To-XML
Type Mappings. Each attribute customizes how the XmlSerializer maps a class,
field or property to an XML document. The attributes can also declare types
that are not explicitly referenced in a source file.
Serialization
Attribute
Purpose
XmlRootAttribute
Specify a name
different from the class name for the root element of a serialization
hierarchy
XmlElementAttribute
Specify the element
name for a field or property. The XmlElementAttribute also omits the array
node when it is applied to collections or arrays. The Type property can
provide additional type information and limits the customizations of the
attribute to a particular class.
XmlAttributeAttribute
Generate an attribute
rather than an element node for the field or property and specify the XML
attribute’s name.
XmlArrayAttribute
Change the name of
an array node
XmlArrayItemAttribute
Similar to the
XmlElementAttribute. It changes array element names. The Type property can
provide additional type information and limits the customizations of the
attribute to a particular class. Use the NestingLevel property on an array of
arrays to specify which level of depth the attribute applies to.
XmlIgnoreAttribute
Ignore a field or
property for serialization.
XmlEnumAttribute
Change the name of
an enum element
XmlTextAttribute
Serialized a field
or property as XML text.
XmlChoiceIdentifierAttribute
Provide additional
information to map an xsd:choice to the .NET type system
XmlNamespaceDeclarationAttribute
Declare namespace
prefixes to use when serializing or deserializing an object.
XmlIncludeAttribute
Specify related
types.
XmlTypeAttribute
Specify the XSD
schema type and change the element name
XmlAnyAttributeAttribute
Setup a field or
property to receive XML attributes that do not map to any fields or
properties of the class. The field or property must be an array of XmlNode or
XmlAttribute.
XmlAnyElementAttribute
Setup a field or
property to receive XML elements that do not map to any fields or properties
of the class. The field or property must be an array of XmlNode or
XmlElement.
DefaultValueAttribute
Specifies the XSD
default value for a field. The serializer will not serialize the field if it
is set to the default value. The receiver has to infer the default value from
the schema.
Let’s see how which of these attributes we can apply to our Car class to get the desired output from the XmlSerializer.
First we attach an XmlRootAttribute attribute to change the name of the root
element to “car” with a lower case ‘c’. The new the name of the root element is
passed to the constructor of the attribute.
Second, we would like to map the fields to attributes rather than
elements. We can accomplish this by applying an XmlAttribute to each field. Like the XmlRoot, this attribute
also has a constructor which takes the name to use for the generated XML
attribute as a parameter.
using System.Xml.Serialization;
[XmlRoot("car")]
public class Car
{
public Car(){}
[XmlAttribute("make")]
public string Make;
[XmlAttribute("model")]
public string Model;
[XmlAttribute("year")]
public int Year;
}
Now when we call Serialize() the XmlSerializer will create an XML document
file of the format we wanted:
There is another metadata attribute very similar to the two we
just heard about so it needs to be mentioned here. Similar to the XmlRoot, the XmlElement maps the member name to another XML
element name. While the XmlRoot can only be applied to classes, the XmlAttribute
and the XmlElement are only valid on class members.
Each attribute offers further properties to fine-tune the how the XmlSerializer maps an item to XML. Table 9.4 shows common
properties of many attributes and explains their use. You can also find a
complete reference for the metadata attributes and their properties in the
appendix.
Table 9.4: Common properties exposed by many Xml
serialization attributes. These properties fine-tune the behavior of the
attributes. They define XML namespaces, limit the scope of the attribute to a
certain type, specify the corresponding type in an XSD schema, control the form
of the generated XML and define whether or not the create XML for null
references.
Property
Description
Applies To
DataType
Specifies the XSD
data type of the item, as defined by the W3 consortium. The DataType will be
read by the XSD Schema tool when generating an XSD schema from the class.
Specifies which XML
namespace the generated item belongs to. A namespace declaration will be
added if the namespace is not already declared in the scope of the item.