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

Kri*_*ard 8 c# xml linq

建立

我的Main()功能中有这个.

List<Token> tokens = new List<Token>();
string path = @"\(some directories)\tokens.xml";
XDocument doc = XDocument.Load(path);
Run Code Online (Sandbox Code Playgroud)

我有这个类有几个属性.

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; }
}
Run Code Online (Sandbox Code Playgroud)

我有这个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
Run Code Online (Sandbox Code Playgroud)

如您所见,根元素中有许多<card>元素<cards>.此外,每个都<card>可以具有许多<set>元素.我相应地上课了.

问题

我如何一次<card>浏览一个并为每个属性分配适当的值?

我曾经尝试过什么

我制作了一个列表,其中包含<name>每个元素的所有元素<card>.然后,我将浏览此列表并为Token该类Name属性的新实例指定一个名称.然后tokens用每个新实例填充我的列表.

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);
}
Run Code Online (Sandbox Code Playgroud)

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

编辑

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

XmlSerializer serializer = new XmlSerializer(typeof(Token));
using (StringReader reader = new StringReader(path))
{
    Token token = (Token)(serializer.Deserialize(reader));
}
Run Code Online (Sandbox Code Playgroud)

可能只是一个不正确的实现.如果是这种情况,有人可以使用我发布的内容并向我显示正确的实现吗?另外,我假设这会为我的两个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);
}
Run Code Online (Sandbox Code Playgroud)

Lists我第一次考虑的数量要好得多.不像序列化那样简洁.但是,它做了我需要的.

谢谢您的帮助.

EDIT4

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

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

Dav*_*ave 10

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

我不确定这是否正是你想要完成的,但我相信它应该可以帮助你对多个"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>
Run Code Online (Sandbox Code Playgroud)

我创建了几个类

[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; }
}
Run Code Online (Sandbox Code Playgroud)

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

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));
}
Run Code Online (Sandbox Code Playgroud)

以下是输出的样子.

观看输出