Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 294
John Avatar asked Oct 28 '11 20:10

John


People also ask

How can you modify control the XML that is being generated by XmlSerializer?

By applying the XmlRootAttribute, you can control the XML stream generated by the XmlSerializer. For example, you can change the element name and namespace. The XmlTypeAttribute allows you to control the schema of the generated XML.

Which class should be used to serialize an object in XML format?

Xml. Serialization namespace) class is used to serialize and deserialize. The class method Serialize is called. Since we have to serialize in a file, we create a " TextWriter ".

Why do we use XmlSerializer class?

XmlSerializer enables you to control how objects are encoded into XML. The XmlSerializer enables you to control how objects are encoded into XML, it has a number of constructors.

How does the XmlSerializer work C#?

The XmlSerializer creates C# (. cs) files and compiles them into . dll files in the directory named by the TEMP environment variable; serialization occurs with those DLLs. These serialization assemblies can be generated in advance and signed by using the SGen.exe tool.


3 Answers

Try adding IsNullable = true to the XmlArrayItem attribute.

like image 196
James Johnson Avatar answered Oct 13 '22 21:10

James Johnson


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

like image 41
K2so Avatar answered Oct 13 '22 23:10

K2so


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 ;
}
like image 42
kux Avatar answered Oct 13 '22 23:10

kux