Code Reference A collection of code for my reference (and perhaps other people too)

8Mar/100

Serialization to XML with CDATA tags

Sometimes you need CDATA tags around complex text in your destination XML.

There is no build in way of doing so (that I have found).

I found this nifty CdataWrapper class on Marc Gravell's blog. Thanks Marc!

Here is the basic class.

public sealed class CDataWrapper : IXmlSerializable
{
        // implicit to/from string
        public static implicit operator string(CDataWrapper value)
        {
            return value == null ? null : value.Value;
        }
        public static implicit operator CDataWrapper(string value)
        {
            return value == null ? null : new CDataWrapper
            {
                Value =
                    value
            };
        }
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }
        // "" => <Node/>
        // "Foo" => <Node><![CDATA[Foo]]></Node>
        public void WriteXml(XmlWriter writer)
        {
            if (!string.IsNullOrEmpty(Value))
            {
                writer.WriteCData(Value);
            }
        }
        // <Node/> => ""
        // <Node></Node> => ""
        // <Node>Foo</Node> => "Foo"
        // <Node><![CDATA[Foo]]></Node> => "Foo"
        public void ReadXml(XmlReader reader)
        {
            if (reader.IsEmptyElement)
            {
                Value = "";
            }
            else
            {
                reader.Read();
                switch (reader.NodeType)
                {
                    case XmlNodeType.EndElement:
                        Value = ""; // empty after all...
                        break;
                    case XmlNodeType.Text:
                    case XmlNodeType.CDATA:
                        Value = reader.ReadContentAsString();
                        break;
                    default:
                        throw new InvalidOperationException("Expected text/cdata");
                }
            }
        }
        // underlying value
        public string Value { get; set; }
        public override string ToString()
        {
            return Value;
        }
}

To use it, you must change your DataMember from String to CDataWrapper, make it private and give it a public property.

This:

[DataMember]
pubblic string Answer { get; set; }

Becomes this:

pubblic string Answer { get; set; }
[DataMember(Name="Answer", EmitDefaultValue=false)]
private CDataWrapper AnswerCDATA
{
    get { return Answer; }
    set { Answer = value; }
}

Then the serialization is done with one line:

.
.
.
XElement xml = Microsoft.ServiceModel.Web.SerializationExtensions.ToXml(object);
.

So simple!!!!

8Mar/100

More on Object Serialization to XML

It seems there are hundreds of ways to serialize object.

Here are just a few:

This one now seems very clumbsy. You pass in the object and the object type. It returns a string. I can't see the point of using this one any more now that I have found the next one.

public static string ContractObjectToXml<T>(T obj)
{
    DataContractSerializer dataContractSerializer = new DataContractSerializer(obj.GetType());
    String text;
    using (MemoryStream memoryStream = new MemoryStream())
    {
        dataContractSerializer.WriteObject(memoryStream, obj);
        byte[] data = new byte[memoryStream.Length];
        Array.Copy(memoryStream.GetBuffer(), data, data.Length);
        text = Encoding.UTF8.GetString(data);
    }
    return text;
}

This one I have started using is the most simple I have seen so far.

.
.
.
XElement xml = Microsoft.ServiceModel.Web.SerializationExtensions.ToXml(object);
.

This one returns a stream. It gives you a bit more control over what is shown and included in the XML.

public static Stream Serialize(Object obj)
{
            MemoryStream memoryStream = new MemoryStream();
            DataContractSerializer dcSerializer = new DataContractSerializer(obj.GetType());
            XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
            xmlWriterSettings.Encoding = new UTF8Encoding(false);
            xmlWriterSettings.ConformanceLevel = ConformanceLevel.Document;
            xmlWriterSettings.Indent = true;
            //xmlWriterSettings.OmitXmlDeclaration = true;

            using (XmlWriter xWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
            {
                dcSerializer.WriteObject(xWriter, obj);
                xWriter.Flush();
                //return Encoding.UTF8.GetString(memoryStream.ToArray());
                memoryStream.Position = 0;
                return memoryStream;
            }
}