【问题标题】:Serializing list of nullable CDATA可空 CDATA 的序列化列表
【发布时间】:2016-10-11 11:40:00
【问题描述】:

我正在尝试反序列化一个 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; }
}

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

由于某种原因,反序列化在达到为空的 CDATA 值后停止。

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

有什么建议吗?

谢谢。

【问题讨论】:

  • 为什么Stack 必须是XmlCDataSection 而不仅仅是string?元素数据恰好是 CDATA 转义标记是表示的细节。如果它显示为&lt;Stack&gt;This is some cdata, where &amp;lt;br&amp;gt; html code is left as is...&lt;/Stack&gt;,您会因为它不是 CDATA 而拒绝它吗? (另外,这是关于de序列化,而不是序列化。)
  • 关于反序列化,那么你是完全正确的。我已经改变了问题中的措辞。关于 CDATA 条目的问题是,我无法更改数据和/或格式。我必须按原样反序列化数据。
  • 只使用public string Stack { get; set; },不带任何属性。

标签: c# .net xml


【解决方案1】:

通过字符串获取 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); } }

指定空元素的正确方法是&lt;Stack xsi:nil='true' /&gt;。有了这个添加,您的反序列化将完美无缺。但是,在第一次出现&lt;Stack /&gt; 时,反序列化器将遇到未知节点。如果您缺少此属性,请订阅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合并。

【讨论】:

    猜你喜欢
    • 2019-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-19
    相关资源
    最近更新 更多