Recently I needed to specify exactly how I would like a specific class serialized. Suppose we have the following simple schema:
<xs:schema targetNamespace="http://my.favourite.ns/person.xsd"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://my.favourite.ns/person.xsd">
<xs:complexType name="Person">
<xs:sequence>
<xs:element name="Name" type="xs:string" />
<xs:element name="Surname" type="xs:string" />
<xs:element name="Age" type="xs:int" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Let's call this schema President.xsd.
A valid XML instance against this schema would be, for example:
<Person xmlns="http://my.favourite.ns/person.xsd">
<Name>Barrack</Name>
<Surname>Obama</Surname>
<Age>47</Age>
</Person>
Since we are serializing against a specific XML schema (XSD), we have an option of schema compilation:
xsd /c President.xsd
This, obviously, yields a programmatic type system result in a form of a C# class. All well and done.
Now.
If we serialize the filled up class instance back to XML, we get a valid XML instance. It's valid against President.xsd.
There is a case where your schema changes ever so slightly - read, the namespaces change, and you don't want to recompile the entire solution to support this, but you still want to use XML serialization. Who doesn't - what do you do?
Suppose we want to get the following back, when serializing:
<PresidentPerson xmlns="http://schemas.gama-system.com/
president.xsd">
<Name>Barrack</Name>
<Surname>Obama</Surname>
<Age>47</Age>
</PresidentPerson>
There is an option to override the default serialization technique of XmlSerializer. Enter the world of XmlAttributes and XmlAttributeOverrides:
private XmlSerializer GetOverridedSerializer()
{
// set overrides for person element
XmlAttributes attrsPerson = new XmlAttributes();
XmlRootAttribute rootPerson =
new XmlRootAttribute("PresidentPerson");
rootPerson.Namespace = "http://schemas.gama-system.com/
president.xsd";
attrsPerson.XmlRoot = rootPerson;
// create overrider
XmlAttributeOverrides xOver = new XmlAttributeOverrides();
xOver.Add(typeof(Person), attrsPerson);
XmlSerializer xSer = new XmlSerializer(typeof(Person), xOver);
return xSer;
}
Now serialize normally:
Stream ms = new MemoryStream();
XmlTextWriter tw = new XmlTextWriter(ms, null);
xSer.Serialize(tw, person);
This will work even if you only have a compiled version of your object graph, and you don't have any sources. System.Xml.Serialization.XmlAttributeOverrides class allows you to adorn any XML serializable class with your own XML syntax - element names, attribute names, namespaces and types.
Remember - you can override them all and still serialize your angle brackets.