如何将XML数据解析为自定义C#类的属性?

建立

我在我的Main()函数中有这个。

 List tokens = new List(); string path = @"\(some directories)\tokens.xml"; XDocument doc = XDocument.Load(path); 

我有这个类有一些属性。

 public partial class Token { public Token() { SetURLs = new List(); SetNames = new List(); } public string Name { get; set; } public List SetURLs { get; set; } public List SetNames { get; set; } public string Color { get; set; } public string PT { get; set; } public string Text { get; set; } } 

我有这个XML文件。 这是一个片段。

  //EDIT3  //EDIT3  . . .  Griffin DDH w  Token 2/2 0 Flying 1   Rat SHM GTC b  Token 1/1 0  1  . . .   //EDIT3 

如您所见, 根元素中有许多元素。 此外,每个可以有许多元素。 我相应地上课了。

问题

如何一次浏览一张并为每个属性分配适当的值?

我曾经尝试过什么

我创建了一个包含每个所有元素的 。 然后,我将浏览此列表并为Token类的Name属性的新实例指定一个名称。 然后使用每个新实例填充我的tokens列表。

 List names = new List(); names = doc.Descendants("card").Elements("name").Select(r => r.Value).ToList(); int amount = doc.Descendants("card").Count(); for(int i = 0; i < amount; i++) { Token token = new Token(); token.Name = name[i]; . . . tokens.Add(token); } 

我想我可以制作更多包含所有其他所需元素的列表并执行相同的过程,但必须有更优雅的方式,对吧?

编辑

我也试过从另一个问题序列化。 但出于某种原因,当我尝试将token中的东西写入控制台(比如token.Name)时,它没有写任何东西。

 XmlSerializer serializer = new XmlSerializer(typeof(Token)); using (StringReader reader = new StringReader(path)) { Token token = (Token)(serializer.Deserialize(reader)); } 

可能只是一个不正确的实现。 如果是这种情况,有人可以使用我发布的内容并向我展示正确的实现吗? 另外,我假设这会为我的两个List属性提供1个或多个值,对吧?

编辑

谢谢您的帮助。

EDIT2

一个答案

经过一些不成功的序列化和一些搜索后,我做了一个有效的实现。

 foreach (var card in doc.Descendants("card")) { Token token = new Token(); token.Name = card.Element("name").Value.ToString(); foreach (var set in card.Elements("set")) { token.SetURLs.Add(set.Attribute("picURL").Value.ToString()); token.SetNames.Add(set.Value.ToString()); } token.Color = card.Element("color").Value.ToString(); token.PT = card.Element("pt").Value.ToString(); token.Text = card.Element("text").Value.ToString(); tokens.Add(token); } 

比我最初想到的Lists数量要好得多。 不像序列化那样简洁。 但是,它做到了我需要的。

谢谢您的帮助。

EDIT4

不确定这些编辑是否允许或违反礼仪。 只是想为未来的读者做这个编辑。

“答案”部分下的内容确实解决了我的问题,但Dave下面发布的XML序列化要好得多; 它更灵活,更容易重用/修改。 因此,选择对您的情况有更多好处的解决方案。

使用XML序列化我能够将您的代码段反序列化为某些对象。 我真的不明白你的2个不同的列表变量,所以我把它修改为1个列表。

我不确定这是否正是你想要完成的,但我相信它应该可以帮助你对多个“set”元素进行xml反序列化。

我创建了一个名为tokens.xml的相同代码段的文件,编辑后与您的新布局相匹配。

     Griffin DDH w  Token 2/2 0 Flying 1   Rat SHM GTC b  Token 1/1 0  1    

我创建了几个类

 [XmlRoot(ElementName = "card_database")] public class CardsDatabase { public CardsDatabase() { } [XmlElement(ElementName = "cards", Form = XmlSchemaForm.Unqualified)] public CardsList Cards { get; set; } [XmlAttribute(AttributeName = "version", Form = XmlSchemaForm.Unqualified)] public string Version { get; set; } } [XmlRoot(ElementName = "cards")] public class CardsList { public CardsList() { Cards = new List(); } [XmlElement(ElementName = "card", Form = XmlSchemaForm.Unqualified)] public List Cards { get; set; } } [XmlRoot(ElementName = "card")] public class Card { public Card() { SetURLs = new List(); } [XmlElement(ElementName = "name", Form = XmlSchemaForm.Unqualified)] public string Name { get; set; } [XmlElement(ElementName = "set", Form = XmlSchemaForm.Unqualified)] public List SetURLs { get; set; } [XmlElement(ElementName = "color", Form = XmlSchemaForm.Unqualified)] public string Color { get; set; } [XmlElement(ElementName = "pt", Form = XmlSchemaForm.Unqualified)] public string PT { get; set; } [XmlElement(ElementName = "text", Form = XmlSchemaForm.Unqualified)] public string Text { get; set; } } [XmlRoot(ElementName = "set")] public class SetItem { public SetItem() { } [XmlAttribute(AttributeName = "picURL", Form = XmlSchemaForm.Unqualified)] public string PicURL { get; set; } [XmlAttribute(AttributeName = "picURLHq", Form = XmlSchemaForm.Unqualified)] public string PicURLHq { get; set; } [XmlAttribute(AttributeName = "picURLSt", Form = XmlSchemaForm.Unqualified)] public string PicURLSt { get; set; } [XmlText] public string Value { get; set; } } 

主体如下(我知道这是丑陋的,但我快速,所以请改进)

 CardsDatabase cards = new CardsDatabase(); string path = @"tokens.xml"; XmlDocument doc = new XmlDocument(); doc.Load(path); XmlSerializer serializer = new XmlSerializer(typeof(CardsDatabase)); using (StringReader reader = new StringReader(doc.InnerXml)) { cards = (CardsDatabase)(serializer.Deserialize(reader)); } 

以下是输出的样子。

观看输出

使用Linq到Xml,

 string path = @"~/tokens.xml"; var doc = XDocument.Load(Server.MapPath(Url.Content(path))); var cards = doc.Descendants("card") .Select(x => new Token { Name = x.Element("name").Value, SetURLs = x.Elements("set").Select(y => y.Attribute("picURL").Value) .ToList(), SetNames = x.Elements("set").Select(y => y.Value).ToList(), Color = x.Element("color").Value, PT = x.Element("pt").Value, Text = x.Element("text").Value }).ToList(); 

希望这可以帮助。

看看这篇文章:

XPath和* .csproj

但是请使用下面的内容并将匿名类型转换为具体类。 它应该足以让你开始。

  XDocument xDoc = /* populate from somewhere */ XNamespace nsPlaceHolder = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003"); XNamespace ns = string.Empty; var list1 = from list in xDoc.Descendants(ns + "cards") from item in list.Elements(ns + "card") /* where item.Element(ns + "card") != null */ select new { PicURL = item.Attribute("picURL").Value, MyName = (item.Element(ns + "name") == null) ? string.Empty : item.Element(ns + "name").Value }; foreach (var v in list1) { Console.WriteLine(v.ToString()); }