序列化可空的CDATA列表

时间:2016-10-11 11:40:00

标签: c# .net xml

我正在尝试反序列化XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<Foos xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FooList>
    <Foo>
      <Bar>bar value</Bar>
      <Stack />
    </Foo>
    <Foo>
      <Bar>bar value</Bar>
      <Stack><![CDATA[This is some cdata, where <br> html code is left as is..]]></Stack>
    </Foo>
  </FooList>
</Foos>

进入以下课程

[XmlRoot("Foos")]
public class Foos
{
    [XmlArray("FooList")]
    [XmlArrayItem("Foo")]
    public List<Foo> FooList { get; set; }
}

public class Foo
{
    public string Bar { get; set; }

    [XmlElement("Stack", typeof(XmlCDataSection))]
    public XmlCDataSection Stack {get; set; }
}

问题是,FooList生成的Foos只包含一(1)个元素,这是第一个Foo块,Slack属性设置为空值。如果我将CDATA值添加到stack,就像第二个Foo块一样,那么我最终会得到两个元素的列表。

出于某种原因,在达到CDATA值为null之后,反序列化停止。

我尝试创建私有字符串并创建Stack的setter和getter,这样就可以使用private属性来存储CDATA字符串。这并没有改变任何事情。

有什么建议吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

通过字符串访问cdata部分。对象模型:

[Serializable]
[XmlRoot("Foos", Namespace="", IsNullable=false)]
public partial class Foos {
    [XmlArrayItem ("Foo", IsNullable=false)] public Foo[] FooList { get; set; } }

[Serializable] public partial class Foo {
    public string Bar { get; set; }
    [XmlIgnore] public string Stack { get; set; }
    [XmlElement("Stack", IsNullable=true)] 
    public XmlCDataSection StackCDATA {
      get { return new XmlDocument().CreateCDataSection(Stack ?? String.Empty); }
      set {
        Stack = value == null 
          ? String.Empty
          : ( String.IsNullOrWhiteSpace(value.Value)
            ? String.Empty
            : value.Value); } }

    public override string ToString() { return String.Format("Bar:{0} Stack:{1}", Bar, Stack); } }

指定null元素的正确方法是<Stack xsi:nil='true' />。通过这个添加,您的反序列化将是完美的。但是,在第一次出现<Stack />时,解串器将遇到未知节点。如果您缺少此属性,请解决此问题,订阅UnknownElement

var fooSrlz = new XmlSerializer(typeof(Foo), new XmlRootAttribute { ElementName = "Foo", IsNullable = true} );
var foosMissedByDeserializer = new List<CData.Foo>();
srlz.UnknownElement += (/*object*/ sender, /*XmlElementEventArgs  */ e) => {
    using (TextReader tr = new StringReader(e.Element.OuterXml)) {
      var foo = (CData.Foo)fooSrlz.Deserialize(tr);
      foosMissedByDeserializer.Add (foo);
    } };  

将反序列化结果与上面的 foosMissedByDeserializer 合并。

相关问题