views:

312

answers:

4

I have defined the following class:

public class Root
{
    public string Name;
    public string XmlString;
}

and created an object:

Root t = new Root 
         {  Name = "Test", 
            XmlString = "<Foo>bar</Foo>" 
         };

When I use XmlSerializer class to serialize this object, it will return the xml:

<Root>
  <Name>Test</Name>
  <XmlString>&lt;Foo&gt;bar&lt;/Foo&gt;</XmlString>
</Root>

How do I make it not encode my XmlString content so that I can get the serialized xml as

<XmlString><Foo>bar</Foo></XmlString>

Thanks, Ian

+1  A: 

I would be very surprised if this was possible. Suppose it was possible for you to do this - what would happen if you had malformed XML in the property - everything would just break.

I expect that you will either need to write your own serialization for this case, or make it so that the XmlString field is a structure that contains a foo field.

garethm
+2  A: 

You can (ab)use the IXmlSerializable interface an XmlWriter.WriteRaw for that. But as garethm pointed out you then pretty much have to write your own serialization code.

using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace ConsoleApplicationCSharp
{
  public class Root : IXmlSerializable
  {
    public string Name;
    public string XmlString;

    public Root() { }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
      writer.WriteElementString("Name", Name);
      writer.WriteStartElement("XmlString");
      writer.WriteRaw(XmlString);
      writer.WriteFullEndElement();
    }

    public void ReadXml(System.Xml.XmlReader reader) { /* ... */ }
    public XmlSchema GetSchema() { return (null); }
    public static void Main(string[] args)
    {
      Root t = new Root
      {
        Name = "Test",
        XmlString = "<Foo>bar</Foo>"
      };
      System.Xml.Serialization.XmlSerializer x = new XmlSerializer(typeof(Root));
      x.Serialize(Console.Out, t);
      return;
    }
  }
}

prints

<?xml version="1.0" encoding="ibm850"?>
<Root>
  <Name>Test</Name>
  <XmlString><Foo>bar</Foo></XmlString>
</Root>
VolkerK
Does it deserialize too?
configurator
If you implement the ReadXml(XmlReader reader) method, yes.
VolkerK
+1  A: 

try this:

public class Root
{
    public string Name;
    public XDocument XmlString;
}

Root t = new Root 
         {  Name = "Test", 
            XmlString = XDocument.Parse("<Foo>bar</Foo>")
         };
zvolkov
+1  A: 

You can limit the custom serialization to just the element that needs special attention like so.

public class Root
{
    public string Name;

    [XmlIgnore]
    public string XmlString
    {
        get
        {
            if (SerializedXmlString == null)
                return "";
            return SerializedXmlString.Value;
        }
        set
        {
            if (SerializedXmlString == null)
                SerializedXmlString = new RawString();
            SerializedXmlString.Value = value;
        }
    }

    [XmlElement("XmlString")]
    [Browsable(false)]
    [EditorBrowsable(EditorBrowsableState.Never)]
    public RawString SerializedXmlString;
}

public class RawString : IXmlSerializable
{
    public string Value { get; set; }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        this.Value = reader.ReadInnerXml();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteRaw(this.Value);
    }
}
Cameron MacFarland
+1, I'd prefer this over my class Root : IXmlSerializable approach.
VolkerK