我在我的Main()函数中有这个.
List<Token> tokens = new List<Token>(); string path = @"\(some directories)\tokens.xml"; XDocument doc = XDocument.Load(path);
我有这个类有一些属性.
public partial class Token { public Token() { SetURLs = new List<string>(); SetNames = new List<string>(); } public string Name { get; set; } public List<string> SetURLs { get; set; } public List<string> SetNames { get; set; } public string Color { get; set; } public string PT { get; set; } public string Text { get; set; } }
我有这个XML文件.这是一个片段.
<?xml version="1.0" encoding="UTF-8"?> //EDIT3 <card_database version="2"> //EDIT3 <cards> . . . <card> <name>Griffin</name> <set picURL="http://magiccards.info/extras/token/duel-decks-ajani-vs-nicol-bolas/griffin.jpg" picURLHq="" picURLSt="">DDH</set> <color>w</color> <manacost></manacost> <type>Token</type> <pt>2/2</pt> <tablerow>0</tablerow> <text>Flying</text> <token>1</token> </card> <card> <name>Rat</name> <set picURL="http://magiccards.info/extras/token/shadowmoor/rat.jpg" picURLHq="" picURLSt="">SHM</set> <set picURL="http://magiccards.info/extras/token/gatecrash/rat.jpg" picURLHq="" picURLSt="">GTC</set> <color>b</color> <manacost></manacost> <type>Token</type> <pt>1/1</pt> <tablerow>0</tablerow> <text></text> <token>1</token> </card> . . . </cards> </card_database> //EDIT3
如你所见,有很多< card> < cards>中的元素根元素.此外,每个< card>可以有很多< set>元素.我相应地上课了.
问题
我如何通过一个< card>一次并为每个属性分配适当的值?
我曾经尝试过什么
我制作了一个包含所有< name>的列表每个< card>的元素.然后,我将浏览此列表并为Token类的Name属性的新实例指定一个名称.然后使用每个新实例填充我的令牌列表.
List<string> names = new List<string>(); 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.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); }
比我最初想到的列表数量要好得多.不像序列化那样简洁.但是,它做到了我需要的.
谢谢您的帮助.
EDIT4
不确定这些编辑是否允许或违反礼仪.只是想为未来的读者做这个编辑.
“答案”部分下的内容确实解决了我的问题,但Dave下面发布的XML序列化要好得多;它更灵活,更容易重用/修改.因此,选择对您的情况有更多好处的解决方案.
我不确定这是否正是你想要完成的,但我相信它应该可以帮助你对多个“set”元素进行xml反序列化.
我创建了一个名为tokens.xml的相同代码段的文件,编辑后与您的新布局相匹配.
<?xml version="1.0" encoding="UTF-8"?> <card_database version="2"> <cards> <card> <name>Griffin</name> <set picURL="http://magiccards.info/extras/token/duel-decks-ajani-vs-nicol-bolas/griffin.jpg" picURLHq="" picURLSt="">DDH</set> <color>w</color> <manacost></manacost> <type>Token</type> <pt>2/2</pt> <tablerow>0</tablerow> <text>Flying</text> <token>1</token> </card> <card> <name>Rat</name> <set picURL="http://magiccards.info/extras/token/shadowmoor/rat.jpg" picURLHq="" picURLSt="">SHM</set> <set picURL="http://magiccards.info/extras/token/gatecrash/rat.jpg" picURLHq="" picURLSt="">GTC</set> <color>b</color> <manacost></manacost> <type>Token</type> <pt>1/1</pt> <tablerow>0</tablerow> <text></text> <token>1</token> </card> </cards> </card_database>
我创建了几个类
[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<Card>(); } [XmlElement(ElementName = "card",Form = XmlSchemaForm.Unqualified)] public List<Card> Cards { get; set; } } [XmlRoot(ElementName = "card")] public class Card { public Card() { SetURLs = new List<SetItem>(); } [XmlElement(ElementName = "name",Form = XmlSchemaForm.Unqualified)] public string Name { get; set; } [XmlElement(ElementName = "set",Form = XmlSchemaForm.Unqualified)] public List<SetItem> 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)); }
以下是输出的样子.