简体   繁体   中英

How to serialize an object containing an XML property

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

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM