views:

425

answers:

1

I have the following code:

public class Foo {}

static class Program {
    [XmlElement("foo")] // Ignored :(
    static public List<Foo> MyFoos { get; private set; }

    public static void Main() {
        MyFoos.Add(new Foo());
        MyFoos.Add(new Foo());

        XmlSerializer configSerializer = 
            new XmlSerializer(typeof(List<Foo>), new XmlRootAttribute("foos"));
        using (TextWriter w = new StreamWriter("test.xml"))
        {
            s.Serialize(w, MyFoos);
        }
    }
}

Which produces the following XML file:

<?xml version="1.0" encoding="utf-8"?>
<foos xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <Foo />
  <Foo />
</foos>

What I would really like to have is the Foo elements labeled as foo, instead... I realise this is mostly cosmetic, but it fits with what is generally considered normal in XML.

+5  A: 

It should work if you set the element name directly ...

   [XmlElement( ElementName = "foo" )]

See example here. Is the point that it has to be static? If so, this is not helpful, but this works fine (added the round trip per comment) ...

namespace TestSerial
{
    public class Foo
    {
        public int Value
        {
            get;
            set;
        }
    }
    public class SerializeMe
    {
        private List<Foo> _foos = new List<Foo>();
        public SerializeMe()
        {
        }

        [XmlElement("foo")]
        public List<Foo> MyFoos { get { return _foos; } }

    }

    class Program
    {
        static void Main(string[] args)
        {
            var fs = new SerializeMe();
            fs.MyFoos.Add(new Foo() { Value = 1 });
            fs.MyFoos.Add(new Foo() { Value = 2 });

            var s = new XmlSerializer(typeof(SerializeMe), new XmlRootAttribute("foos"));
            using (var w = new StreamWriter(@"c:\temp\test.xml"))
            {
                s.Serialize(w, fs);
            }

            using (var r = new StreamReader(@"c:\temp\test.xml"))
            {
                var o = s.Deserialize(r);
                var fs2 = (SerializeMe)o;

                fs2.MyFoos.Select(f => f.Value).ToList().ForEach(Console.WriteLine);
            }

            Console.ReadLine();
        }
    }
}


EDIT: (Matthew, OP)

My final solution, which I consider a refinement of the above was:

public class Foo {}

[XmlRoot("foos")]
public class FooList 
{
    public FooList() { Foos = new List<Foo>(); }
    [XmlElement("foo")]
    public List<Foo> Foos { get; set; }
}

static class Program 
{
    static private FooList _foos = new FooList();
    static public List<Foo> MyFoos { get { return _foos; } }

    public static void Main() 
    {
        MyFoos.Add(new Foo());
        MyFoos.Add(new Foo());

        XmlSerializer configSerializer = 
            new XmlSerializer(typeof(FooList));

        using (TextReader r = new StreamReader("test.xml"))
        {
            _foos = (FooList)configSerializer.Deserialize(r);
        }

        using (TextWriter w = new StreamWriter("test.xml"))
        {
            configSerializer.Serialize(w, _foos);
        }
    }
}
JP Alioto
XmlElementAttribute isn't allowed on class definitions: Attribute 'XmlElement' is not valid on this declaration type. It is only valid on 'property, indexer, field, param, return' declarations.
Matthew Scharley
He has it on a property, no?
JP Alioto
It's a static property and will always be ignored.
John Saunders
Ah! Bitten by the toy example I guess.
JP Alioto
Something I'd like to avoid... but does it work properly with deserialising it again too? (I'm slightly worried about the lack of a setter on the property, but I'm new to this)
Matthew Scharley
I'm going to edit this and add my final solution, since I find it a bit cleaner than this one, but it is based heavily on this one, so it should be accepted.
Matthew Scharley