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><ConfigurationX>SomeConfiguration1</ConfigurationX></XmlConfiguration>
</SubObject>
<SubObject>
<XmlConfiguration><ConfigurationY>SomeConfiguration2</ConfigurationY></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.
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);
}
}