Introduction
This tip shows the differences in XML serialization when a serializable class has a combination of [XmlElement]
and [XmlText]
.
Background
XML serialization can be done in various ways and techniques. In this tip, I would like to show a difference I experienced with a serializable class declaring a collection as [XmlElement]
and a string
as [XmlText]
.
Using the Code
Serializable Class
This class has the following properties:
- A
string
as an attribute - [XmlAttribute]
- A
string
as a text attribute - [XmlText]
- A
collection
as an element - [XmlElement]
[XmlType(AnonymousType = true)]
public class Person
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlText]
public string Text { get; set; }
[XmlElement("person")]
public Collection<Person> Children { get; set; }
public bool ShouldSerializeChildren()
{
return Children != null && Children.Count > 0;
}
public string Serialize()
{
var sw = new StringWriter();
var serializer = new XmlSerializer(typeof(Person));
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
serializer.Serialize(sw, this, ns);
return sw.ToString();
}
}
Serializing the Class Without Assigning a Text Property
Assigning only the name
attribute and the collection
element.
var person = new Person
{
Name = "name",
Children =
new Collection<Person>
{
new Person {Name = "child1", Text = "child1Text"},
new Person {Name = "child2", Text = "child2Text"}
}
};
var personWithoutText = person.Serialize();
Console.WriteLine("Person without text attribute has new lines:");
Console.WriteLine("-------------------------------------------");
Console.WriteLine(personWithoutText);
Console.WriteLine();
The Result
The result would be a nice indented XML with newlines between the collection items.
="1.0"="utf-16"
<Person name="name">
<person name="child1">child1Text</person>
<person name="child2">child2Text</person>
</Person>
Serializing the Class After Assigning a Text Property
person.Text = "text";
var personWithTextAttribue = person.Serialize();
Console.WriteLine("Person with text attribute has no new lines:");
Console.WriteLine("-------------------------------------------");
Console.WriteLine(personWithTextAttribue);
Console.ReadLine();
The Result
The result would be an XML without newlines between the collection items.
="1.0"="utf-16"
<Person name="name">text<person name="child1">child1Text</person>
<person name="child2">child2Text</person></Person>
Conclusion
The workaround I found for having newlines between collection items, was to make sure there is no text attribute in the serializable class.
Points of Interest
Why did I declare the collection property as XmlElement
?
A collection that is not declared as XmlElement
, its items are encoded as a sequence of elements, nested under an element named after the property. (See XmlElementAttribute in MSDN)
Something like this:
<myserializableclass>
<wrappingelement>
<item>item1</item>
<item>item2</item>
<item>item3</item>
<myserializableclass>
</myserializableclass>
In order to avoid the element wrapping the collection's items, I am declaring the collection as [XmlElement]
.
The serialization result would then be:
<MySerializableClass>
<item>item1</item>
<item>item2</item>
<item>item3</item>
</MySerializableClass>
History
- 14th February, 2015: Initial version
- 17th February, 2015: Edited conclusion and updated code (fixed namespace and XML attributes)