John
John

Reputation: 16007

How to decorate/define class members for an optional XML element to be used with XmlSerializer?

I have the following XML structure. The theElement element can contain theOptionalList element, or not:

<theElement attrOne="valueOne" attrTwo="valueTwo">
    <theOptionalList>
        <theListItem attrA="valueA" />
        <theListItem attrA="anotherValue" />
        <theListItem attrA="stillAnother" />
    </theOptionalList>
</theElement>
<theElement attrOne="anotherOne" attrTwo="anotherTwo" />

What is a clean way to express the corresponding class structure?

I'm pretty sure of the following:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace MyNamespace
{
    public class TheOptionalList
    {
        [XmlAttributeAttribute("attrOne")]
        public string AttrOne { get; set; }

        [XmlAttributeAttribute("attrTwo")]
        public string AttrTwo { get; set; }

        [XmlArrayItem("theListItem", typeof(TheListItem))]
        public TheListItem[] theListItems{ get; set; }

        public override string ToString()
        {
            StringBuilder outText = new StringBuilder();

            outText.Append("attrOne = " + AttrOne + " attrTwo = " + AttrTwo + "\r\n");

            foreach (TheListItem li in theListItems)
            {
                outText.Append(li.ToString());
            }

            return outText.ToString();
        }
    }
}

As well as:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace MyNamespace
{
    public class TheListItem
    {
        [XmlAttributeAttribute("attrA")]
        public string AttrA { get; set; }

        public override string ToString()
        {
            StringBuilder outText = new StringBuilder();

            outText.Append("  attrA = " + AttrA + "\r\n");                
            return outText.ToString();
        }
    }
}

But what about for theElement? Do I take the theOptionalList element as an array type to have it read what it finds in the file (either nothing, or one) and then check in code whether it's there or not? Or is there another decorator that I can supply? Or does it just work?

EDIT: I ended up using information from this answer.

Upvotes: 6

Views: 24698

Answers (3)

Kux
Kux

Reputation: 1489

Additional to the XxySpecifed property, there is also a method with a ShouldSerialize prefix

[XmlElement]
public List<string> OptionalXyz {get; set;}

public bool ShouldSerializeOptionaXyz() {
    return OptionalXyz != null && OptionalXyz.Count > 0 ;
}

Upvotes: 1

James Johnson
James Johnson

Reputation: 46067

Try adding IsNullable = true to the XmlArrayItem attribute.

Upvotes: 10

K2so
K2so

Reputation: 982

It looks like you can use another bool to specify to include an element or not.

Another option is to use a special pattern to create a Boolean field recognized by the XmlSerializer, and to apply the XmlIgnoreAttribute to the field. The pattern is created in the form of propertyNameSpecified. For example, if there is a field named "MyFirstName" you would also create a field named "MyFirstNameSpecified" that instructs the XmlSerializer whether to generate the XML element named "MyFirstName". This is shown in the following example.

public class OptionalOrder
{
    // This field should not be serialized 
    // if it is uninitialized.
    public string FirstOrder;

    // Use the XmlIgnoreAttribute to ignore the 
    // special field named "FirstOrderSpecified".
    [System.Xml.Serialization.XmlIgnoreAttribute]
    public bool FirstOrderSpecified;
}

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx

Upvotes: 6

Related Questions