BizTalk Utilities CV ,   Jobs ,   Code library  
 
Home Page
XmlSerializer
XmlSerializer
Serialization Attributes
Serializable Classes
Deserializing an object
Serializing an object
Serialize Class
Metadata Attributes
<< XML DOM
XQuery >>

By :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.
First posted :03/24/2008
Times viewed :2750

 

XmlIncludeAttribute

An XmlInclude attribute attached to a class will let the serializer know about derived classes. The XmlSerializer cannot handle situations where an object of a derived type occurs if a base type was declared without some help from us, regardless whether the derived type occurs at the root or somewhere else in the serialized object graph. The XmlSerializer needs to know about types derived from a class at the time it does its class analysis, i.e. when the constructor runs. If we do not explicitly declare the derived type together with the base type the constructor is not able to locate the derived type on its own and cannot create and process a type mapping for the derived type.

Applying this attribute is very useful when you are developing your own class library that maps to a hierarchy of XML schema types, where a derived type can also replace a base type. Take the following XSD snippet for example, which defines a base type Vehicle and two derived type Car and Motorcycle:

<!-- base type -->

<xs:element name="Vehicle" nillable="true" type="Vehicle" />

<xs:complexType name="Vehicle">

  <xs:sequence>

    <xs:element minOccurs="1" maxOccurs="1" name="Make"

      type="xs:string" />

    <xs:element minOccurs="1" maxOccurs="1" name="Model"

      type="xs:string" />

    <xs:element minOccurs="1" maxOccurs="1" name="Year" type="xs:int" />

  </xs:sequence>

</xs:complexType>

<!-- 1st derived type -->

<xs:complexType name="Motorcycle">

  <xs:complexContent mixed="false">

    <xs:extension base="Vehicle">

    </xs:extension>

  </xs:complexContent>

</xs:complexType>

<!-- 2nd derrived base type -->

<xs:complexType name="Car">

  <xs:complexContent mixed="false">

    <xs:extension base="Vehicle">

    </xs:extension>

  </xs:complexContent>

</xs:complexType>

<xs:element name="Car" nillable="true" type="Car" />

<xs:element name="Motorcycle" nillable="true" type="Motorcycle" />

Any element in this schema of type Vehicle could also contain a Car or a Motorcycle type, because Car and Motorcycle are extensions of Vehicle – just like we can replace a base class with a derived class in a class hierarchy in an object-oriented programming environment. We can easily map this hierarchy to a set of the .NET classes. We need a base class

Vehicle and two derived classes Car and Motorcycle, like the ones in listing 9.4.

Listing  9.1: Vehicle class hierarchy with the XmlInclude attribute

[XmlInclude(typeof(Car))]

[XmlInclude(typeof(Motorcycle))]

public class Vehicle       | #1

{

  public Vehicle(){}

  public string Make;

  public string Model;

  public int Year;

}

public class Car : Vehicle | #2

{

  public Car() {}

  public string VIN;      | #3

}

public class Motorcycle : Vehicle  | #4

{

  public Motorcycle() {}

}

(annotation) <#1 The base class of the hierarchy>

(annotation) <#2 The first class derived from Vehicle>

(annotation) <#3 The Car class adds an additional field>

(annotation) <#4  Another class derived from Vehicle>

We have to annotate the Vehicle class with an XmlInclude attribute for each of the derived classes, if we want the XmlSerializer to be able to serialize Car and Motorcycle objects where a Vehicle was declared.

NOTE: The XmlInclude attribute works recursively, i.e. the serializer will also include types if the XmlInclude attribute was attached to a class that was included because of a class that was already included through an XmlInclude attribute.

With the XmlInclude attributes in place an XmlSerializer will know how to serialize and deserialize Car and Motorcycle objects instead of a Vehicle object, because the XmlSerializer found the XmlInclude attributes, analyzed the types Car and Motorcycle and made a reference that each of those are valid substitutes for the Vehicle type. To prove it we can create an XmlSerializer for the Vehicle type and use it to serialize a Car object:

Car wifesCar = new Car();

XmlSerializer xs = new XmlSerializer(typeof(Vehicle));

xs.Serialize(xw, wifesCar);

The code doesn’t throw an exception, that’s already an indication that everything went as expected.

Serialize() identified the type of the wifesCar object, found a type mapping for the Car type and wrote the following XML to the output: 

<Vehicle

  xmlns:xsd=http://www.w3.org/2001/XMLSchema

  xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance

  xsi:type="Car">

  <Make>Ford</Make>

  <Model>Explorer</Model>

  <Year>1997</Year>

  <VIN>1234</VIN>

</Vehicle>

 

The name of the root element indicates that the serialized object was declared to be of type Vehicle. In this case the XmlSerializer expects a Vehicle object as the serialization root, because we passed Vehicle’s Type to the constructor. The actual type of the serialized object is stored in an xsi:type attribute, for deserialize to determine that the serialized object does not conform to the declared type. The type attribute belongs to the XSD schema-instance namespace and declares an element’s XSD schema type. Here the type attribute indicates that the element is of type Car. Also note that all fields of the Car class are present in the XML output, not only the members of the Vehicle class.

NOTE: The Deserialize() method will read xsi:type attributes and throw an exception if it does not find a matching mapping for the type. Without the xsi:type attribute it would deserialize the XML document to a Vehicle object and ignore the VIN element.


Rate this article on a scale of 1 to 10

Your vote :  


 

Recent Jobs

Integration Specialist Needed - Wor
Virtualization Server Infrastructur
A great opportunity to Digital Vide
here is a greate opportunity as a S
A great opportunity as a Network En

View all Jobs (Add yours)
View all CV (Add yours)




Chicago Web Site Design
affordable conference calls
conference call services
Emporio armani sunglasses
air freshener
odor remover


    Email TopXML  

Front Page Daily Stuff TopXML Forum XML blogs XML Newsgroups BizTalk Biztalk Utilities Biztalk Utilities Tutorial B2B SAP XML Microsoft .NET Dotnet System XML Soapformatter SQLXML XMLserializer XQuery PHP PHP SimpleXML PHP XML Dom PHP XML RPC PHP XSLT Java Java Java XML Xalan Microsoft ASP ASP Schemas XML SQL Server XML XMLDom XSL XSL Tutorial XSLT Stylesheets General Javascript CSS XHTML WAP