Classes:
public class Employee
{
public int Id { get; set; }
public PhoneNumber[] Numbers { get; set; }
}
public class PhoneNumber
{
public string Type { get; set; }
public string Number { get; set; }
}
Code to serialize:
var xmlSerializer = new XmlSerializer(typeof(Employee));
var xwSettings = new XmlWriterSettings {Indent = true, OmitXmlDeclaration = true};
string serializedResult;
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, xwSettings))
{
xmlSerializer.Serialize(writer, emp);
serializedResult = stream.ToString();
}
Current Result:
<Employee>
<Id>1</Id>
<Numbers>
<PhoneNumber>
<Type>Home</Type>
<Number>1231231231</Number>
</PhoneNumber>
<PhoneNumber>
<Type>Office</Type>
<Number>3453453453</Number>
</PhoneNumber>
</Numbers>
</Employee>
Desired Result:
<Employee>
<Id>1</Id>
<Numbers>
<Home>1231231231</Home>
<Office>3453453453</Office>
</Numbers>
</Employee>
PhoneNumber
Type
can be added dynamically like "GuestRoomPhone" etc, so adding properties for each phone number type is not an option.
You can do this by implementing the IXmlSerializable
interface on your classes. This allows you to control how the values are written and read.
public class Employee : IXmlSerializable
{
public int Id { get; set; }
public PhoneNumber[] Numbers { get; set; }
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement("Employee");
reader.ReadStartElement("Id");
Id = reader.ReadContentAsInt();
reader.ReadEndElement(); // Id
reader.ReadStartElement("Numbers");
List<PhoneNumber> numbers = new List<PhoneNumber>();
while (reader.MoveToContent() == XmlNodeType.Element)
{
PhoneNumber num = new PhoneNumber();
num.ReadXml(reader);
numbers.Add(num);
}
Numbers = numbers.ToArray();
reader.ReadEndElement(); // Numbers
reader.ReadEndElement(); // Employee
}
public void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("Id");
writer.WriteValue(Id);
writer.WriteEndElement();
writer.WriteStartElement("Numbers");
foreach (PhoneNumber num in Numbers)
{
num.WriteXml(writer);
}
writer.WriteEndElement(); // Numbers
}
}
Similarly for the PhoneNumber
class.
public class PhoneNumber : IXmlSerializable
{
public string Type { get; set; }
public string Number { get; set; }
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
while (!reader.IsStartElement())
reader.Read();
Type = reader.Name;
Number = reader.ReadElementContentAsString();
}
public void WriteXml(XmlWriter writer)
{
writer.WriteStartElement(Type);
writer.WriteString(Number);
writer.WriteEndElement();
}
}