2

I'm having trouble producing the following XML-structure using the XmlSerializer:

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>This is root.</Name>
  <OtherValue>Otha.</OtherValue>
  <Shapes Name="This attribute is ignored!">
    <Circle>
      <Name>This</Name>
      <Value>Is</Value>
      <Whatever>Circle</Whatever>
    </Circle>
    <Square>
      <Name>And</Name>
      <Value>this is</Value>
      <Something>Square</Something>
    </Square>
  </Shapes>
</Root>

The only problem is that the attributes of <Shapes> doesn't get written. The classes I'm using for the serialization are the following:

public class Root
{
    [XmlElement]
    public string Name { get; set; }

    [XmlElement]
    public string OtherValue { get; set; }

    [XmlArray("Shapes")]
    [XmlArrayItem("Circle", typeof(Circle))]
    [XmlArrayItem("Square", typeof(Square))]
    public ShapeList Shapes { get; set; }
}

public class ShapeList : List<Shape>
{
    // Attribute that is not in output
    [XmlAttribute]
    public string Name { get; set; }
}

public class Shape
{
    public string Name { get; set; }
    public string Value { get; set; }
}

public class Circle : Shape
{
   public string Whatever { get; set; }
}

public class Square : Shape
{
    public string Something { get; set; }
}

And a little main method to run the serialization:

public static void Main(String[] args)
{
    var extraTypes = new Type[] {
        typeof(Shape),
        typeof(Square),
        typeof(Circle)
    };

    var root = new Root();
    root.Name = "This is root.";
    root.OtherValue = "Otha.";

    root.Shapes = new ShapeList()
    {
        new Circle() { Name = "This", Value="Is", Whatever="Circle" },
        new Square() { Name = "And", Value="this is", Something="Square" }
    };
    root.Shapes.Name = "This is shapes.";

    using (var sw = new StreamWriter("data.xml"))
    {
        var serializer = new XmlSerializer(typeof(Root), extraTypes);
        serializer.Serialize(sw, root);
    }
}
  • Why am I not getting the Name attribute of the ShapeList?
  • If this cannot be accomplished using this method, is there any another simple way?

1 Answer 1

3

Attributes are not processed for the outer part of arrays; only leaf nodes are processed for that - collections are just: their contents. There is a way to do it, if you don't mind making the model a bit more complex....

public class Root
{
    [XmlElement]
    public string Name { get; set; }

    [XmlElement]
    public string OtherValue { get; set; }

    [XmlElement("Shapes")]
    public ShapeContainer Shapes { get; set; }
}

public class ShapeContainer
{
    [XmlAttribute]
    public string Name { get; set; }

    private readonly List<Shape> items = new List<Shape>();
    [XmlElement("Circle", typeof(Circle))]
    [XmlElement("Square", typeof(Square))]
    public List<Shape> Items { get { return items; } }
}

public class Shape
{
    public string Name { get; set; }
    public string Value { get; set; }
}

public class Circle : Shape
{
    public string Whatever { get; set; }
}

public class Square : Shape
{
    public string Something { get; set; }
}

with usage changed as follows:

root.Shapes = new ShapeContainer();
root.Shapes.Items.Add(new Circle() { Name = "This", Value="Is", Whatever="Circle" });
root.Shapes.Items.Add(new Square() { Name = "And", Value = "this is", Something = "Square" });
root.Shapes.Name = "This is shapes.";
Sign up to request clarification or add additional context in comments.

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.