65.9K
CodeProject is changing. Read more.
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (4 votes)

Feb 14, 2015

CPOL

1 min read

viewsIcon

29386

downloadIcon

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

<?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

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

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