Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net XmlSerializer: deserialize CDATA being inner text

I have a problem with CDATA deserialization using standard .Net XmlSerializer.

Update: I get XML from external system and I can't influence it's format so I can't make CData be enclosed in a separate Element of Attribute.

Serialization gives this:

<?xml version="1.0" encoding="utf-16"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><![CDATA[Hello, world!]]></MyClass>

Deserialization does not restore object to it's original state.

Here's class that is being serialized:

public class MyClass
{
    string _data;

    [XmlIgnore]
    public string Data
    {
        get { return _data; }
        set { _data = value; }
    }

    [XmlAnyElement]
    public XmlCDataSection CData
    {
        get { return new XmlDataDocument().CreateCDataSection(Data); }
        set { Data = value.Value; }
    }
}

Here's the test which fails:

[Test]
public void CData_as_inner_text_test()
{
    MyClass item = new MyClass();

    item.Data = "Hello, world!";

    XmlSerializer serializer = new XmlSerializer(item.GetType());
    string serialized;

    using (StringWriter sw = new StringWriter())
    {
        serializer.Serialize(sw, item);
        serialized = sw.GetStringBuilder().ToString();
    }

    MyClass deserialized;

    using (StringReader sr = new StringReader(serialized))
    {
        deserialized = (MyClass)serializer.Deserialize(sr);
    }

    Assert.AreEqual(item.Data, deserialized.Data); // For some reason, deserialized.Data == null
}

I found the same problem here but there's no answer: XmlSerializer, XmlAnyElement and CDATA

like image 438
Konstantin Spirin Avatar asked Dec 29 '08 03:12

Konstantin Spirin


1 Answers

The CData property ends up null, because the content of the CDATA section ends up in the Data property, where it is being ignored...

<MyClass><![CDATA[Hello, world!]]></MyClass>

is absolutely equivalent to:

<MyClass>Hello, world!</MyClass>

You shouldn't care whether the external app writes the content of MyClass as CData or not. Likewise, the external app shouldn't care how you write it out.

IOW, this should be all you need:

public class MyClass
{
    string _data;

    [XmlText]
    public string Data
    {
        get { return _data; }
        set { _data = value; }
    }
}
like image 162
oefe Avatar answered Nov 07 '22 14:11

oefe