【问题标题】:Deserialize xml into list of objects将 xml 反序列化为对象列表
【发布时间】:2017-11-10 05:03:06
【问题描述】:

我正在尝试将一些 xml 反序列化为对象列表。

我遇到麻烦的地方是 Resources 对象中的辅助对象 Event 没有填充值。对于更多背景知识,这是一个统一项目,我正在反序列化可能发生的随机事件列表。

下面是我正在测试的 XML:

<?xml version='1.0'?>
<Events>
  <Event>
    <Description>
      this is a test
    </Description>
    <Reward>
        <Food>
          0
        </Food>
        <Energy>
          1
        </Energy>
        <Happiness>
          2
        </Happiness>
        <ShipHp>
          3
        </ShipHp>
        <Garbage>
          4
        </Garbage>
    </Reward>
    <Cost>
        <Food>
          0
        </Food>
        <Energy>
          1
        </Energy>
        <Happiness>
          2
        </Happiness>
        <ShipHp>
          3
        </ShipHp>
        <Garbage>
          4
        </Garbage>
    </Cost>
    <EventType>
      Good
    </EventType>
    <EventId>
      1
    </EventId>
  </Event>
  <Event>
    <Description>
      this is a test
    </Description>
    <Reward>
        <Food>
          0
        </Food>
        <Energy>
          1
        </Energy>
        <Happiness>
          2
        </Happiness>
        <ShipHp>
          3
        </ShipHp>
        <Garbage>
          4
        </Garbage>
    </Reward>
    <Cost>
        <Food>
          0
        </Food>
        <Energy>
          1
        </Energy>
        <Happiness>
          2
        </Happiness>
        <ShipHp>
          3
        </ShipHp>
        <Garbage>
          4
        </Garbage>
    </Cost>
    <EventType>
      Good
    </EventType>
    <EventId>
      1
    </EventId>
  </Event>
</Events>

这里是对象(事件和资源):

public class Event {
    [XmlElement("Description")]
    public string Description { get; set; }

    [XmlElement("Reward")]
    public Resources Reward { get; set; }

    [XmlElement("Cost")]
    public Resources Cost { get; set; }

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

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

}

[XmlType("Resources")]
public class Resources {

    //Each prop can be extended to food being a Food object with expiry, etc
    [XmlElement("Food")]
    public int Food { get; set; } // 0 to cap
    [XmlElement("Happiness")]
    public int Happiness { get; set; } // 0 to 100
    [XmlElement("Energy")]
    public int Energy { get; set; } //0 to cap
    [XmlElement("ShipHp")]
    public int ShipHp { get; set; }// cap to 0
    [XmlElement("Garbage")]
    public int Garbage { get; set; } // 0 to cap
}

这是我的反序列化代码:

   public class EventHandler : MonoBehaviour
{

    [XmlInclude(typeof(Event))]
    [XmlInclude(typeof(Resources))]
    [Serializable, XmlRoot("Events")]
    public class EventData
    {
        [XmlElement("Event")]
        public List<Event> Events { get; set; }

        public EventData()
        {
            List<Event> Events = new List<Event>();
        }
    }

    List<Event> Events = new List<Event>();
    public static EventHandler instance;

    // Use this for initialization, called on script enabling
    void Start()
    {

        var serializer = new XmlSerializer(typeof(EventData));
        try
        {
            string xml = File.ReadAllText("Assets/TextResources/Events.xml");
            xml = xml.Replace("\n", string.Empty);
            xml = xml.Replace("\r", string.Empty);
            xml = xml.Replace("\t", string.Empty);
            using (var stringReader = new StringReader(xml))
            {
                using (var reader = XmlReader.Create(stringReader))
                {
                    var result = (EventData)serializer.Deserialize(reader);
                    Events = result.Events;

                }
            }
        }
        catch(Exception ex)
        {
            Debug.Log(ex);
        }
    }
}

所以从这段代码中,我的事件对象被填充了 Description、EventType 和 EventId 的值,但 Reward 和 Cost 资源对象没有被填充这些值,到目前为止,我不知道为什么会这样。对于加分,我也在努力寻找一种方法来简单地删除我从解析字符串中获得的所有死空间。 (即 Good 更改为“\n\r Good”)。

【问题讨论】:

    标签: c# xml


    【解决方案1】:

    好的。所以我找到了解决问题的方法,我不是这方面的专家,所以如果有任何更正,更有经验的人想要添加以改进代码,我很乐意进行更改。

    首先,我的 XML 存在格式问题,为了找到这个问题,我实际上序列化了一个事件对象列表并使用生成的文本来找到解决方案,下面是修改后的文本:

    <ArrayOfEvent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <Event>
        <Description>abc</Description>
        <Reward>
          <Food>0</Food>
          <Happiness>2</Happiness>
          <Energy>1</Energy>
          <ShipHp>3</ShipHp>
          <Garbage>4</Garbage>
        </Reward>
        <Cost>
          <Food>0</Food>
          <Happiness>2</Happiness>
          <Energy>1</Energy>
          <ShipHp>3</ShipHp>
          <Garbage>4</Garbage>
        </Cost>
        <EventId>1</EventId>
        <EventType>Good</EventType>
      </Event>
      <Event>
        <Description>def</Description>
        <Reward>
          <Food>0</Food>
          <Happiness>2</Happiness>
          <Energy>1</Energy>
          <ShipHp>3</ShipHp>
          <Garbage>4</Garbage>
        </Reward>
        <Cost>
          <Food>0</Food>
          <Happiness>2</Happiness>
          <Energy>1</Energy>
          <ShipHp>3</ShipHp>
          <Garbage>4</Garbage>
        </Cost>
        <EventId>2</EventId>
        <EventType>Good</EventType>
      </Event>
    </ArrayOfEvent>
    

    首先要注意的是我序列化了一个事件对象列表,这是&lt;ArrayOfEvent&gt; 标记和生成的xml 名称空间属性。从此。这也意味着我必须从EventData 类更改为List&lt;Event&gt;,这样更方便。从我的Event 和Resources 类中,我将[Serializable, XmlRoot()] 标记添加到它们的类中。 需要注意的另一件事是,我将EventType 从字符串交换为枚举,该枚举的代码也将在下面提供 这些修复还修复了我从 xml 纯文本到 XmlReader 的格式问题 我将下面的完整代码分享给未来的读者:

    [Serializable, XmlRoot("Event")]
    public class Event
    {
        [XmlElement("Description")]
        public string Description { get; set; }
    
        [XmlElement("Reward")]
        public Resources Reward { get; set; }
    
        [XmlElement("Cost")]
        public Resources Cost { get; set; }
    
        [XmlElement("EventId")]
        public int EventId { get; set; }
    
        [XmlElement("EventType")]
        public EventType EventType { get; set; }
        [XmlIgnore]
        public string MarkUp { get; set; }
    }
    
    
    [Serializable, XmlRoot("Resources")]
    public class Resources
    {
        //Each prop can be extended to food being a Food object with expiry, etc
        [XmlElement("Food")]
        public int Food { get; set; } // 0 to cap
        [XmlElement("Happiness")]
        public int Happiness { get; set; } // 0 to 100
        [XmlElement("Energy")]
        public int Energy { get; set; } //0 to cap
        [XmlElement("ShipHp")]
        public int ShipHp { get; set; }// cap to 0
        [XmlElement("Garbage")]
        public int Garbage { get; set; } // 0 to cap
    }
    
    [XmlType("EventType")]
    public enum EventType
    {
        [XmlEnum("Good")]
        Good = 0,
        [XmlEnum("Bad")]
        Bad,
        [XmlEnum("Neutral")]
        Neutral
    }
    
    
    public class EventHandler : MonoBehaviour
    {
    
        List<Event> Events = new List<Event>();
    
        // Use this for initialization, called on script enabling
        void Start()
        {
            try
            {
                var serializer = new XmlSerializer(typeof(List<Event>));
    
                string xml = File.ReadAllText("Assets/TextResources/Events.xml");
                xml = XDocument.Parse(xml).ToString(SaveOptions.DisableFormatting);
    
                using (var stringReader = new StringReader(xml))
                {
                    using (var reader = XmlReader.Create(stringReader))
                    {
                        var result = (List<Event>)serializer.Deserialize(reader);
                        Events = result;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Log(ex);
            }
        }
    }
    

    基本序列化方法

    private void serializeList()
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<Event>));
        List<Event> list = new List<Event>();
        list.Add(new Event { EventId = 1, Description = "abc", EventType = EventType.Good, Cost = new Resources { Food = 0, Energy = 1, Happiness = 2, ShipHp = 3, Garbage = 4 }, Reward = new Resources { Food = 0, Energy = 1, Happiness = 2, ShipHp = 3, Garbage = 4 } });
        list.Add(new Event { EventId = 2, Description = "def", EventType = EventType.Good, Cost = new Resources { Food = 0, Energy = 1, Happiness = 2, ShipHp = 3, Garbage = 4 }, Reward = new Resources { Food = 0, Energy = 1, Happiness = 2, ShipHp = 3, Garbage = 4 } });
        list.Add(new Event { EventId = 3, Description = "ghi", EventType = EventType.Good, Cost = new Resources { Food = 0, Energy = 1, Happiness = 2, ShipHp = 3, Garbage = 4 }, Reward = new Resources { Food = 0, Energy = 1, Happiness = 2, ShipHp = 3, Garbage = 4 } });
        StreamWriter sw = new StreamWriter("Assets/TextResources/test.xml");
        ser.Serialize(sw, list);
        sw.Close();
    }
    

    【讨论】:

      【解决方案2】:

      您的 XML 无效。您的第一个 Resources 标签永远不会关闭。

      【讨论】:

      • 感谢您的反馈,虽然这是一个问题,但不是大问题
      猜你喜欢
      • 2013-12-16
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      • 2020-10-31
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多