3

Suppose I have the following class structure:

[XmlInclude(typeof(CustomNode))]
[XmlInclude(typeof(CustomNode2))]
[XmlRoot("node")]
class Node
{
    [XmlElement("node")]
    public Node[] Children { get; set; }
}
[XmlRoot("custom-node")]
class CustomNode : Node { }
[XmlRoot("custom-node-2")]
class CustomNode2 : Node { }

The I create the following structure:

var root = new Node { Children = new Node[2] };
root.Children[0] = new CustomNode();
root.Children[1] = new CustomNode2();

When I Xml serialize this structure, I get following output:

<node>
    <node xsi:Type="CustomNode"/>
    <node xsi:Type="CustomNode2"/>
</node>

But I would like to see (and be able to load properly) something like this:

<node>
    <custom-node/>
    <custom-node-2/>
</node>

Is it possible at all for XmlSerializer? The whole problem is because I intend to manually create source xml, and am trying to make it more humanreadble and friendly.

2 Answers 2

9

I found a solution for your problem which is nearly what you need:

  [XmlRoot(ElementName = "node")]
  public class Node
  {
    [XmlArrayItem(typeof(CustomNode), ElementName = "custom-node")]
    [XmlArrayItem(typeof(CustomNode2), ElementName = "custom-node-2")] 
    public List<Node> Children { get; set; }     
  }
  [XmlRoot(ElementName = "custom-node")]
  public class CustomNode : Node { }
  [XmlRoot(ElementName = "custom-node-2")]
  public class CustomNode2 : Node { }

results in:

<node xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Children>
    <custom-node />
    <custom-node-2 />
  </Children>
</node>

Hope that helps a bit.

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

2 Comments

You are right, my sample will not work without those XmlInclude attributes. But this does not change the output of serialization.
Thanks! That is what I need. I only changed XmlArrayItem to XmlElement, because I don't want to have a container around them. But anyway this works fine.
0

I don't think you'll be able persuade the XmlSerializer to output this xml if you are only using the various xml attibutes to specify the xml.

The [XmlRoot] attribute you are attempting to use is ignored if the type is not itself at the root (rather than being composed in another class).

However, you can implement the IXmlSerializable interface and provide an implementation for IXmlSerializable.WriteXml, which the XmlSerializer will call if present.

This will allow you to craft the xml you want directly to an XmlWriter.

If you also need to deserialize, you'll need to provide an equivalent implementation for IXmlSerializable.ReadXml as well.

2 Comments

This seems to make whole idea of using XmlSerializer meaningless. I could just write custom serialization/deserialization code myself.
Not really - imagine you had a whole graph of objects and there was just one in the middle of the graph whose behaviour you wanted to change. Using this approach, you can leave the default serialization in place for all the other types in the graph, and just override the one that needs customisation. If you just write a load of custom stuff without using IXmlSerializable, you'd have to write a custom implementation for ever object in the graph.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.