【问题标题】:Deserialize XML by walking into the tree: There was an error reflecting type通过走进树反序列化 XML:有一个错误反映类型
【发布时间】:2020-01-08 04:42:05
【问题描述】:

我有这个 XML 作为 API 的结果。使用 DotNetXmlDeserializer 作为反序列化器。

<results>
   <result inum=\"802469000014312\">
      <field name=\"startedat\">2019-09-04T15:59:56.372</field>
      <field name=\"duration\">8</field>
      <field name=\"otherparties\">1043 (DEMO BLA BLA), 0519331839</field>
      <field name=\"switchcallid\">00001000081567605580</field>
      <field name=\"udfs\"></field>
   </result>
   <result inum=\"802469000014313\">
      <field name=\"startedat\">2019-09-04T16:00:31.414</field>
      <field name=\"duration\">6</field>
      <field name=\"otherparties\">1043 (DEMO BLA BLA), 0519331839</field>
      <field name=\"switchcallid\">00001000091567605608</field>
      <field name=\"udfs\"></field>
   </result>

我正在使用这些类进行反序列化

[XmlRoot("results")]
public class WFOQueryDTO_List
{
    public WFOQueryDTO_List() { Items = new List<WFOQueryDTO_Out>(); }
    [XmlElement("result")]
    public List<WFOQueryDTO_Out> Items { get; set; }
}

public class WFOQueryDTO_Out
{
    [XmlElement("field")]
    [XmlAttribute("startedat")]
    public DateTime startedat { get; set; }

    [XmlElement("field")]
    [XmlElement("duration")]
    public int duration { get; set; }


    [XmlElement("field")]
    [XmlElement("otherparties")]
    public string otherparties { get; set; }

    [XmlElement("field")]
    [XmlElement("switchcallid")]
    public string switchcallid { get; set; }

    [XmlElement("field")]
    [XmlElement("udfs")]
    public string udfs { get; set; }

}

但我明白了:

 System.InvalidOperationException: There was an error reflecting type ...For non-array types, you may use the following attributes: XmlAttribute, XmlText, XmlElement, or XmlAnyElement.

【问题讨论】:

  • 字段元素需要私有和公共属性。所以你需要一个get/set接口。简单。将尽快发布答案

标签: c# .net xml serialization


【解决方案1】:

基本上,XmlSerializer 不直接支持该形状。您需要分两步完成:

  1. 使用原始字段列表反序列化
  2. 通过手动识别每个字段名称,将原始字段映射到 WFOQueryDTO_Out 的实际字段,为每个命名字段应用所需的任何类型解析逻辑

“原始字段列表”是指:

[XmlElement("field")]
public List<Field> Fields {get;} = new List<Field>();

public class Field {
    [XmlAttribute("name")]
    public string Name {get;set;}

    [XmlText]
    public string Value {get;set;}
}

要做到这一点正确(并且很容易),您需要输入更典型的强定义形式的 xml:

<startedat>2019-09-04T15:59:56.372</startedat>
<duration>8</duration>
<otherparties>1043 (DEMO BLA BLA), 0519331839</otherparties>
<switchcallid>00001000081567605580</switchcallid>
<udfs></udfs>

【讨论】:

    【解决方案2】:

    这里是完整的解决方案

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Serialization;
    using System.IO;
    
    namespace ConsoleApplication128
    {
        class Program
        {
            static void Main(string[] args)
            {
                string xml =
                    "<root>" +
                       "<results>" +
                          "<result inum=\"802469000014312\">" +
                             "<field name=\"startedat\">2019-09-04T15:59:56.372</field>" +
                             "<field name=\"duration\">8</field>" +
                             "<field name=\"otherparties\">1043 (DEMO BLA BLA), 0519331839</field>" +
                             "<field name=\"switchcallid\">00001000081567605580</field>" +
                             "<field name=\"udfs\"></field>" +
                          "</result>" +
                          "<result inum=\"802469000014313\">" +
                             "<field name=\"startedat\">2019-09-04T16:00:31.414</field>" +
                             "<field name=\"duration\">6</field>" +
                             "<field name=\"otherparties\">1043 (DEMO BLA BLA), 0519331839</field>" +
                             "<field name=\"switchcallid\">00001000091567605608</field>" +
                             "<field name=\"udfs\"></field>" +
                          "</result>" +
                       "</results>" +
                    "</root>";
                StringReader sReader = new StringReader(xml);
                XmlReader xReader = XmlReader.Create(sReader);
                XmlSerializer serializer = new XmlSerializer(typeof(Root));
                Root root = (Root)serializer.Deserialize(xReader);
    
            }
        }
        [XmlRoot("root")]
        public class Root
        {
            [XmlArray("results")]
            [XmlArrayItem("result")]
            public WFOQueryDTO_Out[] WFOQueryDTO_Out { get; set; } 
        }
        public class WFOQueryDTO_Out
        {
            private DateTime startedat { get; set; }
            private int duration { get; set; }
            private string otherparties { get; set; }
            private string switchcallid { get; set; }
            private string udfs { get; set; }
    
            [XmlElement("field")]
            public Field[] field
            {
                get { return new Field[1]; }
                set
                {
                    foreach(Field _field in value)
                    {
                        switch (_field.name)
                        {
                            case "startedat":
                                startedat = DateTime.Parse(_field.value);
                                break;
                            case "duration":
                                duration = int.Parse(_field.value);
                                break;
                            case "otherparties" :
                                otherparties = _field.value;
                                break;
                            case "switchcallid" :
                                switchcallid = _field.value;
                                break;
                            case " udfs" :
                                udfs = _field.value;
                                break;
                        }
                    }
                }
            }
    
        }
        public class Field
        {
    
            [XmlAttribute("name")]
            public string name { get; set; }
            [XmlText]
            public string value { get; set; }
        }
    
    }
    

    【讨论】:

    • 感谢您的努力。这个解决方案看起来不错。无论如何,它不会为第一个回答添加更多内容。
    • 另一种解决方案返回所有字符串。我的解决方案获取日期、整数和字符串。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-14
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 2014-03-13
    • 1970-01-01
    相关资源
    最近更新 更多