Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom node names with XML serialization (.NET)

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">
  <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.

like image 246
Matthew Scharley Avatar asked Dec 17 '22 07:12

Matthew Scharley


1 Answers

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);
        }
    }
}
like image 150
JP Alioto Avatar answered Dec 22 '22 00:12

JP Alioto