Search code examples
c#xmlescapingxml-serializationxmlserializer

How to prevent XmlSerialzer from escaping "nested XML"?


I am using an XmlSerializer to serialize / deserialize complex objects. One property contains an XML string that should be written into a string property without deserialization.

Example (executable in LinqPad):

[XmlRoot("RootObject")]
[Serializable]
public class RootClass
{
    [XmlArray("SubObjects")]
    [XmlArrayItem("SubObject")]
    public SubClass[] SubObjecs { get; set;} 
}

[Serializable]
public class SubClass
{
    [XmlElement("XmlConfiguration")]
    public string XmlConfiguration { get; set;}
}

void Main()
{
    var obj = new RootClass()
    {
        SubObjecs = new[]
        {
            new SubClass { XmlConfiguration = "<ConfigurationX>SomeConfiguration1</ConfigurationX>" },
            new SubClass { XmlConfiguration = "<ConfigurationY>SomeConfiguration2</ConfigurationY>" }
        }
    };

    var serializer = new XmlSerializer(typeof(RootClass));
    using (var stream = new MemoryStream())
    {
        serializer.Serialize(stream, obj);
        stream.Position = 0;
        Console.WriteLine(Encoding.UTF8.GetString(stream.GetBuffer()));
    }
}

The output of the example is:

<?xml version="1.0"?>
<RootObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <SubObjects>
        <SubObject>
            <XmlConfiguration>&lt;ConfigurationX&gt;SomeConfiguration1&lt;/ConfigurationX&gt;</XmlConfiguration>
        </SubObject>
        <SubObject>
            <XmlConfiguration>&lt;ConfigurationY&gt;SomeConfiguration2&lt;/ConfigurationY&gt;</XmlConfiguration>
        </SubObject>
    </SubObjects>
</RootObject>

The XML is a configuration file that is sometimes written programmatically, but mainly written / modified by humans. Therefore the XML within XmlConfiguration should not contain escaped characters.

Question: Is it possible to prevent the XmlSerializer from escaping the '<' and '>' characters? If not, Is there another serializer that can be used?

One option that works is XmlWriter.WriteRaw. However, if somehow possible I would avoid that unreliable and less maintainable solution.


I found a similar question here: How to prevent XmlSerializer from escaping < and > characters. But that question is related to !CDATA[[Content]] and has no answer for my problem.


Solution

  • As mentioned above in comment by dbc, there is a solution that uses the XmlAnyElement attribute as described here: Deserialize dynamic XML


    I found a solution that is a mixture of XmlSerializer and XmlWriter.WriteRaw. When implementing IXmlSerializable, it is possible to control the serialization process of the XmlSerializer. Therfore IXmlSerializable has to be implemented just for the class that needs special handling (which is OK for me):

    [Serializable]
    public class SubClass : IXmlSerializable
    {
        [XmlElement("XmlConfiguration")]
        public string XmlConfiguration { get; set; }
    
        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("XmlConfiguration");
            writer.WriteRaw(XmlConfiguration);
            writer.WriteEndElement();
        }
    
        public void ReadXml(XmlReader reader)
        {
            reader.ReadToDescendant("XmlConfiguration");
            XmlConfiguration = reader.ReadInnerXml();
            reader.ReadEndElement();
        }
    
        public XmlSchema GetSchema()
        {
            return (null);
        }
    }