XML反序列化为C#类遇XmlSports未预期错误,求解决
问题
现有如下XML内容:
<XmlSports CreateDate="2022-12-04T17:47:53.5569879Z"> <Sport Name="eSports" ID="2357"> <Event Name="NBA2K, NBA Blitz League" ID="66838" IsLive="false" CategoryID="9357"> <Match Name="LA Clippers (THA KID) Esports - Milwaukee Bucks (SHARPSHOOTER)" ID="2711992" StartDate="2022-12-04T17:36:00" MatchType="Live"> <Bet Name="Money Line" ID="43859970" IsLive="true"> <Odd Name="1" ID="297613016" Value="2.26"/> <Odd Name="2" ID="297613021" Value="1.58"/> </Bet> <Bet Name="Spread" ID="43859969" IsLive="true"> <Odd Name="1" ID="297614398" Value="1.83" SpecialBetValue="2.5"/> <Odd Name="2" ID="297614399" Value="1.90" SpecialBetValue="2.5"/> </Bet> <Bet Name="Total" ID="43859971" IsLive="true"> <Odd Name="Over" ID="297613741" Value="1.86" SpecialBetValue="140.5"/> <Odd Name="Under" ID="297613740" Value="1.86" SpecialBetValue="140.5"/> </Bet> </Match> </Event> <Event Name="FIFA, GT League" ID="62647" IsLive="false" CategoryID="8212"> ... <!-- 内容过长省略 --> </Event> </Sport> </XmlSports>
目标是将其反序列化为C#类,现有类定义如下:
Sport类
using System.Xml.Serialization; namespace BettingDataAPI.Models { [Serializable, XmlRoot("Sport")] public class Sport { [XmlElement("ID")] public int ID { get; set; } [XmlElement("Name")] public string Name { get; set; } [XmlElement("Event")] public List<Event> Events { get; set; } } }
Event类
using System.Xml.Serialization; namespace BettingDataAPI.Models { [XmlType("Event")] public class Event { [XmlElement("ID")] public int ID { get; set; } [XmlElement("Name")] public string Name { get; set; } [XmlElement("CategoryID")] public int CategoryID { get; set; } [XmlElement("IsLive")] public bool IsLive { get; set; } [XmlElement("Match")] public List<Match> Matches { get; set; } } }
另有Odd、Match和Bet类,反序列化代码如下:
private static async Task<Sport> DeserializeXMLToObject() { private static readonly string xmlUrl = @"*此处为实际URL*"; XmlSerializer ser = new XmlSerializer(typeof(Sport)); HttpClient client = new HttpClient(); HttpResponseMessage response = client.GetAsync(xmlUrl).Result; string xml = ""; if (response.IsSuccessStatusCode) { xml = response.Content.ReadAsStringAsync().Result; } Sport sport = new Sport(); using(TextReader reader = new StringReader(xml)) { sport = (Sport)ser.Deserialize(reader); } return sport; }
执行sport = (Sport)ser.Deserialize(reader);时触发错误:
InnerException = {"<XmlSports xmlns=''> was not expected."}
此前曾创建XmlSports类,但因Entity Framework代码优先迁移时无法为该类生成主键而移除,改为将Sport设为根类。尝试从XML生成XSD文件也失败,寻求解决建议。
解决方案
1. 重新添加XmlSports根类并规避EF主键问题
错误核心是XML根元素是XmlSports,但你用XmlSerializer(typeof(Sport))反序列化,导致根元素不匹配。必须添加对应根类,同时用[NotMapped]标记让EF不为它生成数据库表,避免主键问题:
using System.Xml.Serialization; using System.ComponentModel.DataAnnotations.Schema; namespace BettingDataAPI.Models { [XmlRoot("XmlSports")] [NotMapped] // 告诉EF不要为这个类创建表 public class XmlSports { [XmlAttribute("CreateDate")] public DateTime CreateDate { get; set; } [XmlElement("Sport")] public Sport Sport { get; set; } } }
2. 修正类的XML序列化属性
你之前的类用了[XmlElement]对应XML子元素,但原XML中ID、Name等都是元素属性(比如<Sport Name="eSports" ID="2357">),需要改成[XmlAttribute]才能正确映射:
修正后的Sport类
using System.Xml.Serialization; namespace BettingDataAPI.Models { [XmlType("Sport")] public class Sport { [XmlAttribute("ID")] public int ID { get; set; } [XmlAttribute("Name")] public string Name { get; set; } [XmlElement("Event")] public List<Event> Events { get; set; } } }
修正后的Event类
using System.Xml.Serialization; namespace BettingDataAPI.Models { [XmlType("Event")] public class Event { [XmlAttribute("ID")] public int ID { get; set; } [XmlAttribute("Name")] public string Name { get; set; } [XmlAttribute("CategoryID")] public int CategoryID { get; set; } [XmlAttribute("IsLive")] public bool IsLive { get; set; } [XmlElement("Match")] public List<Match> Matches { get; set; } } }
示例Match类(参考修正)
using System.Xml.Serialization; namespace BettingDataAPI.Models { [XmlType("Match")] public class Match { [XmlAttribute("ID")] public int ID { get; set; } [XmlAttribute("Name")] public string Name { get; set; } [XmlAttribute("StartDate")] public DateTime StartDate { get; set; } [XmlAttribute("MatchType")] public string MatchType { get; set; } [XmlElement("Bet")] public List<Bet> Bets { get; set; } } }
示例Bet类(参考修正)
using System.Xml.Serialization; namespace BettingDataAPI.Models { [XmlType("Bet")] public class Bet { [XmlAttribute("ID")] public int ID { get; set; } [XmlAttribute("Name")] public string Name { get; set; } [XmlAttribute("IsLive")] public bool IsLive { get; set; } [XmlElement("Odd")] public List<Odd> Odds { get; set; } } }
示例Odd类(参考修正)
using System.Xml.Serialization; namespace BettingDataAPI.Models { [XmlType("Odd")] public class Odd { [XmlAttribute("ID")] public int ID { get; set; } [XmlAttribute("Name")] public string Name { get; set; } [XmlAttribute("Value")] public decimal Value { get; set; } [XmlAttribute("SpecialBetValue")] public decimal? SpecialBetValue { get; set; } // 可选属性用可空类型 } }
3. 修正反序列化代码的异步逻辑
原代码用.Result阻塞异步操作,容易引发死锁,改成正确的await写法:
private static async Task<Sport> DeserializeXMLToObject() { var xmlUrl = @"*此处为实际URL*"; var ser = new XmlSerializer(typeof(XmlSports)); // 改为序列化XmlSports类型 using (var client = new HttpClient()) { var response = await client.GetAsync(xmlUrl); if (!response.IsSuccessStatusCode) { return null; // 或处理错误情况 } var xml = await response.Content.ReadAsStringAsync(); using (var reader = new StringReader(xml)) { var xmlSports = (XmlSports)ser.Deserialize(reader); return xmlSports.Sport; } } }
内容的提问来源于stack exchange,提问作者IDK
相关产品推荐
相关产品推荐

