Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

c# - .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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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; }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...