5

This is my first question on Stack Overflow. Apologies in advance if I don't do things quite right while I'm learning how things work here.

Here is my code :

public void TestSerialize()
{
    ShoppingBag _shoppingBag = new ShoppingBag();
    Fruits _fruits = new Fruits();
    _fruits.testAttribute = "foo";

    Fruit[] fruit = new Fruit[2];
    fruit[0] = new Fruit("pineapple");
    fruit[1]= new Fruit("kiwi");

    _fruits.AddRange(fruit);

    _shoppingBag.Items = _fruits;

    Serialize<ShoppingBag>(_shoppingBag, @"C:\temp\shopping.xml");
}

public static void Serialize<T>(T objectToSerialize, string filePath) where T : class
{
    XmlSerializer serializer = new XmlSerializer(typeof(T));

    using (StreamWriter writer = new StreamWriter(filePath))
    {
        serializer.Serialize(writer, objectToSerialize);
    }
}

[Serializable]
public class ShoppingBag
{
    private Fruits _items;

    public Fruits Items
    {
        get { return _items; }
        set {_items = value; }
    }
}

public class Fruits : List<Fruit>
{
    public string testAttribute { get; set; }
}

[Serializable]
public class Fruit 
{
    public Fruit() { }

    public Fruit(string value)
    {
        Name = value;
    }

    [XmlAttribute("name")]
    public string Name { get; set; }
}

It produces this XML :

<?xml version="1.0" encoding="utf-8" ?> 
<ShoppingBag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Items>
    <Fruit name="pineapple" /> 
    <Fruit name="kiwi" /> 
  </Items>
</ShoppingBag>

I don't understand why I am not getting <Items testAttribute="foo">

Please can anyone tell me what I need to add to my code so that the Serializer will write this attribute out?

Thanks,

2
  • 3
    @martin-65, welcome to SO. This is a very good question and should serve as an example of how to ask questions even to more seasoned users on this site. You've correctly formated your code, provided a complete working example (which is easy to reproduce on any PC) isolating the problem, provided the output of the snippet and explained what is the desired result. Commented Aug 28, 2010 at 19:13
  • Thanks for the welcome, and the encouragement. Commented Aug 28, 2010 at 20:40

2 Answers 2

2

You need an intermediary class there:

class Program
{
    static void Main()
    {
        var shoppingBag = new ShoppingBag
        {
            Items = new ShoppingBagItems
            {
                Fruits = new List<Fruit>(new[] {
                    new Fruit { Name = "pineapple" },
                    new Fruit { Name = "kiwi" },
                }),
                TestAttribute = "foo"
            }
        };
        var serializer = new XmlSerializer(typeof(ShoppingBag));
        serializer.Serialize(Console.Out, shoppingBag);
    }
}

public class ShoppingBag
{
    public ShoppingBagItems Items { get; set; }
}

public class ShoppingBagItems
{
    [XmlElement("Fruit")]
    public List<Fruit> Fruits { get; set; }

    [XmlAttribute("testAttribute")]
    public string TestAttribute { get; set; }
}

public class Fruit
{
    [XmlAttribute("name")]
    public string Name { get; set; }
}

Also note that you don't need to decorate your classes with the [Serializable] attribute as it is used only for binary serialization. Another remark is that you don't need to derive from List<T>, simply use it as a property.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer, Darin. I do not understand what you mean when you say that I need an intermediary class. You have used 3 classes (ShoppingBag, ShoppingBagItems, Fruit) as I did (ShoppingBag, Fruits, Fruit). Thanks for the tip about not needing the [Serializable] attribute. Your point about List<T> is the crux of my problem. If I change my original code so as not to derive Fruits from List<T>, then it works fine ...
However, back at work I have been requested to derive from List<T> so that when I deserialize the XML I can easily use foreach on my classes (without having to implement IEnumerable myself). (My XML has 7 levels of objects; I am not performing the Serialization, just the Deserialization. What started this was that I was not able to read an attribute at level 4 and so I thought if I could serialize it correctly then I should be able to deserialize it). So, why does deriving from List<T> stop the attribute being written? and how can I both derive from List<T> and write/read that attribute?
0

Unfortunately, when serializing a collection the XmlSerializer doesn't take into account the extra properties of that collection. It only considers the members that implement ICollection<T>. If you want to serialize extra attributes, you need to wrap the collection in another class that is not a collection itself.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.