Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / XML

Differences in XML Serialization when [XmlElement] and [XmlText] are Combined

4.78/5 (4 votes)
14 Feb 2015CPOL1 min read 29.4K   74  
This tip shows the differences in XML serialization when a serializable class has a combination of [XmlElement] and [XmlText].

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]
C#
[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.

C#
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.

XML
<?xml version="1.0" encoding="utf-16"?>
<Person name="name">
  <person name="child1">child1Text</person>
  <person name="child2">child2Text</person>
</Person>

Serializing the Class After Assigning a Text Property

C#
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.

XML
<?xml version="1.0" encoding="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:

XML
<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:

XML
<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)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)