views:

1181

answers:

2

Is it possible via an attribute of some sort to serialize a string as CDATA using the .Net XmlSerializer?

+5  A: 
[XmlRoot("root")]
public class Sample1Xml
{
    internal Sample1Xml()
    {
    }

    [XmlElement("node")]
    public NodeType Node { get; set; }

    #region Nested type: NodeType

    public class NodeType
    {
        [XmlAttribute("attr1")]
        public string Attr1 { get; set; }

        [XmlAttribute("attr2")]
        public string Attr2 { get; set; }

        [XmlIgnore]
        public string Content { get; set; }

        [XmlText]
        public XmlNode[] CDataContent
        {
            get
            {
                var dummy = new XmlDocument();
                return new XmlNode[] {dummy.CreateCDataSection(Content)};
            }
            set
            {
                if (value == null)
                {
                    Content = null;
                    return;
                }

                if (value.Length != 1)
                {
                    throw new InvalidOperationException(
                        String.Format(
                            "Invalid array length {0}", value.Length));
                }

                Content = value[0].Value;
            }
        }
    }

    #endregion
}
John Saunders
Very useful. Didn't know this was possible!
Jagd
To me this doesn't seem like the most elegant solution. Is this the only possible way of doing this?
jamesaharvey
I think this is the only way to accomplish this, I've seen this topic elsewhere and always the same answer. The example from Philip is a little cleaner but the same concept. The only other way I know of is to implement your own <a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx">IXmlSerializable</a> on a class that represents the CDATA content.
csharptest.net
+3  A: 

In addition to the way posted by John Saunders, you can use an XmlCDataSection as the type directly, although it boils down to nearly the same thing:

   private string _message;
   [XmlElement("CDataElement")]
   public XmlCDataSection Message
   {  
      get 
      { 
         XmlDocument doc = new XmlDocument();
         return doc.CreateCDataSection( _message);
      }
      set
      {
         _message = value.Value;
      }
   }
Philip Rieck
@Philip, does this work for deserialization? I've been seeing notes saying that the setter will receive an XmlText value.
John Saunders
@John Saunders - It actually receives a XmlCharacterData value in the setter during deserialization, which is what the call to .Value is for in the setter ( I originally had it as ToString() from memory, but that was incorrect. )
Philip Rieck