views:

3451

answers:

1

Hello,

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"&gt;&lt;![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

+5  A: 

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; }
    }
}
oefe
Thanks!It appeared I didn't truly realize what CDATA does.Parser just ignores it and treats it's contents as non-formatted text.There's one minor bug in your answer.My xml is absolutely equivalent to <MyClass>Hello, world!</MyClass>(no '<' and '>' around "Hello, world!")
Konstantin Spirin
Thank you Konstantin for spotting my error. I fixed it now.
oefe