views:

23

answers:

1

I want to create a structure like:

<root>
 <items>
  <myns:a s="a"/>
  <b s="a"/>
 </items>
</root>

Where the items in root are descendant from a common base class. I just cannot get it working. The following snippet creates

<root>
 <items>
  <Base xsi:type="A" s="a"/>
  <Base xsi:type="B" s="a"/>
 </items>
</root>

[Serializable]
[XmlInclude(typeof(A))]
[XmlInclude(typeof(B))]
public class Base
{
}

[Serializable]
public class A : Base
{
    public string a = "a";
}

[Serializable]
public class B : Base
{
    public string b = "b";
}

[Serializable]
public class Root
{
    public List<Base> items = new List<Base>();
}

If I use the XmlType attribute, I can change the xsi:type name, but not the name tag. I also want to use a custom namespace on one of the tags, but if I add Namespace to XmlType, I get an error message saying that the type cannot be found, and XmlInclude has to be added..

I guess this is actually quite simple, I just couldn't find out how..

+2  A: 

Are you looking for XmlArrayItemAttribute?

[Serializable]
public class Root
{
    [XmlArrayItem("a", typeof(A), Namespace = "myns")]
    [XmlArrayItem("b", typeof(B))]
    public List<Base> items = new List<Base>();
}

This will serialize as:

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <items>
    <a xmlns="myns">
      <a>a</a>
    </a>
    <b>
      <b>b</b>
    </b>
  </items>
</Root>

You could also use XmlElementAttribute if you want the items to be direct children of Root instead of having an element for items.

Quartermeister
Nice! Didn't know I use several XmlArrayItem's. This also allowed me to remove the XmlInclude from the base class. Thanks!
simendsjo