- XmlSerializer
- Demonstrating Serialization
- Serialization Attributes
Serialization Attributes
XmlSerializer provides hooks into the serialization process thru annotative declarations called attributes. The .NET framework provides attribute facilities to change the behavior of code without having to modify programmatic logic. Attributes bind to assemblies, classes, methods, properties, fields, or events and wind up in the metadata of an assembly with the rest of the type information during code compilation. Table 1 lists and describes the usage of the most commonly used attributes that the XmlSerializer recognizes.
Table 1 Commonly Used Serialization Attributes
Attribute |
Usage |
Result |
XmlAttributeAttribute |
Public fields or properties |
Serializes field or property as an XML attribute |
XmlElementAttribute |
Public fields or properties |
Serializes field or property as an XML element (default) |
XmlIgnoreAttribute |
Public fields or properties |
Ignores field or property in serialization process |
XmlRootAttribute |
Public class declarations |
Sets the top-most element in the serialization process |
XmlArrayAttribute |
Public field or properties that return an array |
Creates a top-level element that encloses elements representing each item in the array |
To show how to use attributes in a productive manner, this next example compacts and makes a few name changes to the XML output of our Domain hierarchy in Listing 5. The XmlRoot attribute binds a namespace to the root element. The use of XmlAttribute attributes change the serialization default for values from XML elements to XML attributes. The XmlIgnore attribute hides our passwords from prying eyes. Other attributes change the naming scheme using named parameters: ID to GUID, and UserRef to UserGUID.
Listing 5: Class with Attribute Annotations
[XmlRoot(Namespace="urn:SerializeAttrs-Domain")] public class Domain { [XmlAttribute(AttributeName="GUID")] public string ID; [XmlAttribute] public string Name; public User[] Users; public Group[] Groups; } public class User { [XmlAttribute(AttributeName="GUID")] public string ID; [XmlAttribute] public string Name; [XmlIgnore] public string Password; } public class UserRef { [XmlAttribute(AttributeName="GUID")] public string ID; } public class Group { [XmlAttribute(AttributeName="GUID")] public string ID; [XmlAttribute] public string Name; [XmlArray(ElementName="UserGUIDs")] public UserRef[] Users; }
The example copied the rest of the serialization code without change to produce the document in Listing 6. It is truly amazing what a difference in output results from a few changes in input on our part. The XmlSerializer offers additional options for customization and parsing of XML that the reader is strongly encouraged to research if the simple examples above don't fully meet their needs.
Listing 6: XML Document Result from Customization
<?xml version="1.0" encoding="utf-8"?> <Domain xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" GUID="9ba56d20-558b- 40ab-989a-b6b49d81add3" Name="InformIT" xmlns="urn:SerializeAttrs-Domain"> <Users> <User GUID="6ce1d524-dfc8-45bd-aa7f-56ecbe0cd3fa" Name="Dale Michalk" /> <User GUID="14e5cc5a-5563-49a3-a1db-8793be37e6cd" Name="Joe User" /> <User GUID="310ea9aa-dca6-47f5-8ee8-f4c0cc6a72e3" Name="Guest User" /> </Users> <Groups> <Group GUID="bdc9baab-b79f-4ed8-a5e9-07d87687b407" Name="Admins"> <UserGUIDs> <UserRef GUID="6ce1d524-dfc8-45bd-aa7f-56ecbe0cd3fa" /> </UserGUIDs> </Group> <Group GUID="70a10155-4268-458f-8874-59e332ffee61" Name="Users"> <UserGUIDs> <UserRef GUID="6ce1d524-dfc8-45bd-aa7f-56ecbe0cd3fa" /> <UserRef GUID="14e5cc5a-5563-49a3-a1db-8793be37e6cd" /> </UserGUIDs> </Group> <Group GUID="aa86f289-456f-4e15-9f56-51cf1cc65887" Name="Guests"> <UserGUIDs> <UserRef GUID="310ea9aa-dca6-47f5-8ee8-f4c0cc6a72e3" /> </UserGUIDs> </Group> </Groups> </Domain>
Another tool that can help you work with the XML serialization or schemas is the XSD.exe program that comes with the .NET framework SDK. It provides the functionality to generate XML schemas based on class type information or generate a class code based on an XML schema. I ran XSD.exe against the module produced in Listing 2 to build the XSD schema in Listing 7. This utility is a handy addition to your XML toolkit for .NET.
Listing 7: XSD Schema for Our Domain Hierarchy
<?xml version="1.0" encoding="utf-8"?> <schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="" xmlns="http://www.w3.org/2001/XMLSchema"> <element name="Domain" nillable="true" type="Domain" /> <complexType name="Domain"> <sequence> <element minOccurs="1" maxOccurs="1" name="ID" nillable="true" type="string" /> <element minOccurs="1" maxOccurs="1" name="Name" nillable="true" type="string" /> <element minOccurs="1" maxOccurs="1" name="Users" nillable="true" type="ArrayOfUser" /> <element minOccurs="1" maxOccurs="1" name="Groups" nillable="true" type="ArrayOfGroup" /> </sequence> </complexType> <complexType name="ArrayOfUser"> <sequence> <element minOccurs="0" maxOccurs="unbounded" name="User" nillable="true" type="User" /> </sequence> </complexType> <complexType name="User"> <sequence> <element minOccurs="1" maxOccurs="1" name="ID" nillable="true" type="string" /> <element minOccurs="1" maxOccurs="1" name="Name" nillable="true" type="string" /> <element minOccurs="1" maxOccurs="1" name="Password" nillable="true" type="string" /> </sequence> </complexType> <complexType name="ArrayOfGroup"> <sequence> <element minOccurs="0" maxOccurs="unbounded" name="Group" nillable="true" type="Group" /> </sequence> </complexType> <complexType name="Group"> <sequence> <element minOccurs="1" maxOccurs="1" name="ID" nillable="true" type="string" /> <element minOccurs="1" maxOccurs="1" name="Name" nillable="true" type="string" /> <element minOccurs="1" maxOccurs="1" name="Users" nillable="true" type="ArrayOfUserRef" /> </sequence> </complexType> <complexType name="ArrayOfUserRef"> <sequence> <element minOccurs="0" maxOccurs="unbounded" name="UserRef" nillable="true" type="UserRef" /> </sequence> </complexType> <complexType name="UserRef"> <sequence> <element minOccurs="1" maxOccurs="1" name="ID" nillable="true" type="string" /> </sequence> </complexType> <element name="User" nillable="true" type="User" /> <element name="UserRef" nillable="true" type="UserRef" /> <element name="Group" nillable="true" type="Group" /> </schema>
Hopefully our quick tour of object serialization has given you a glimpse of the powerful XML capabilities wielded by the .NET platform. Tools such as XmlSerializer and XSD.exe provide a ton of functionality with a small purchase price. We didn't have to create a single line of DOM code to parse nodes, elements, and attributes; the system handled most of the work for us. This can definitely make life working with XML easier and quicker, especially if you are in a crunch for time, as with most development projects.