Home > Net >  How to serialize an object containing an XML property
How to serialize an object containing an XML property

Time:02-10

Note this is .NET 4.8

I have created this sample code to illustrate the problem

[XmlRoot(ElementName = "RESULT", Namespace = "", IsNullable = false)]
public class Result
{
    public string Message { get; set; }

    public XElement Stuff { get; set; }


    public override string ToString() 
    {
        var ser = new XmlSerializer(GetType());

        using (var stream = new StringWriter())
        {
            ser.Serialize(stream, this);
            return stream.ToString();
        }
    }
}

I will have some XML already that looks like this

<FOO>
      <BAR>Hello World</BAR>
      <BAR2>Hello World</BAR2>
      <BAR3>Hello World</BAR3>
</FOO>

This is assigned to the XElement Stuff property and when an instance of Result is then serialized, you get this XML:

<?xml version="1.0" encoding="utf-16"?>
<RESULT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Message>Hello World</Message>
  <Stuff>
    <FOO>
      <BAR>Hello World</BAR>
      <BAR2>Hello World</BAR2>
      <BAR3>Hello World</BAR3>
    </FOO>
  </Stuff>
</RESULT>

Question: Is there any way to get this result instead?

<?xml version="1.0" encoding="utf-16"?>
<RESULT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Message>Hello World</Message>
  <FOO>
    <BAR>Hello World</BAR>
    <BAR2>Hello World</BAR2>
    <BAR3>Hello World</BAR3>
  </FOO>
</RESULT>

Note: FOO could be Stuff - I don't care (because I know how to change that name) I just don't want two levels of nested XML for that property in the serialised XML

You can play with the sample code here

CodePudding user response:

If you're happy for the root name to be hard-coded, then you can write a wrapper type for the elements and implement IXmlSerializable within.

This is likely preferable to implementing in Result, as I imagine the real type would have more than 2 properties.

A quick and dirty example - I'll leave implementing ReadXml to you (if you need it):

public class ElementsWrapper : IXmlSerializable
{   
    public XElement[] Elements { get; set; }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
    }

    public void WriteXml(XmlWriter writer)
    {
        foreach (var element in Elements)
        {
            element.WriteTo(writer);
        }
    }
}

And change your property in Result to:

public ElementsWrapper FOO { get; set; }

When used, the serialiser for Result will write <FOO>, then delegate to the custom serialisation, and then write </FOO>.

You can see an updated fiddle here.

  • Related