首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我在使用.Descendant从XML文件中检索信息时遇到了问题。

我在使用.Descendant从XML文件中检索信息时遇到了问题。
EN

Stack Overflow用户
提问于 2010-01-02 01:35:12
回答 3查看 133关注 0票数 0

我已经得到了关于这方面的帮助,但有一个简单得多的例子:

代码语言:javascript
复制
<Andromeda>
  <Name>Andromeda</Name>
  <Backstory>The star-born celestial known as Andromeda is a stranger to Newerth. With no memory of her home or her people, she is driven merely by an innate sense that the hellbourne are vile and the mortal inhabitants of Newerth innocent. Her powerful dimensional magic allows her to bring destruction to the daemons or strength to her new-found allies.</Backstory>
  <HeroType>Agility</HeroType>
  <Damage>39-53</Damage>
  <Armor>3.1</Armor>
  <MoveSpeed>295</MoveSpeed>
  <AttackType>Ranged(400)</AttackType>
  <AttackRate>.75</AttackRate>
  <Strength>16</Strength>
  <Agility>27</Agility>
  <Intelligence>15</Intelligence>
  <Icon>Images/Hero/Andromeda.gif</Icon>
  <IconGlow>Images/Hero/gAndromeda.gif</IconGlow>
  <GamePicture>Images/Hero-InGame/Andromeda.png</GamePicture>
  <DotaVersion>Shendelzare Silkwood the Vengeful Spirit</DotaVersion>
</Andromeda>

为了检索信息,我只需使用以下代码:

代码语言:javascript
复制
public List<string> LoadHeroInformation(string NameOfHero)
    {
        List<string> Info = new List<string>();

        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("Name").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("Backstory").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("HeroType").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("Damage").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("Armor").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("MoveSpeed").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("AttackType").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("AttackRate").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("Strength").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("Agility").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("Intelligence").Value);
        Info.Add(HeroInformation.Descendants(NameOfHero).Single().Element("DotaVersion").Value);

        return Info;
    }

现在我有了一个复杂得多的XML文件,但我不知道如何检索它。愿意帮助StackOverflow吗?

下面是XML文件:

代码语言:javascript
复制
<Andromeda>
  <SpellOne>
    <Name>Comet</Name>
    <Icon>Images/Spell/Andromeda/Spell1.gif</Icon>
    <Action>Target Unit</Action>
    <Description>Andromeda rips a comet from her dimension to hurl at an enemy, damaging and stunning them.</Description>
    <Ranks>
      <First>            
        <ManaCost>95</ManaCost>
        <Cooldown>10 Seconds</Cooldown>
        <Effects>Deals 100 Magic damage and stuns target for 1.75 seconds.</Effects>
        <ExtraEffects></ExtraEffects>
      </First>
      <Second>
        <ManaCost>110</ManaCost>
        <Cooldown>10</Cooldown>
        <Effects>Deals 175 Magic damage and stuns target for 1.75 seconds.</Effects>
        <ExtraEffects></ExtraEffects>
      </Second>
      <Third>
        <ManaCost>125</ManaCost>
        <Cooldown>10</Cooldown>
        <Effects>Deals 250 Magic damage and stuns target for 1.75 seconds.</Effects>
        <ExtraEffects></ExtraEffects>
      </Third>
      <Fourth>
        <ManaCost>140</ManaCost>
        <Cooldown>10</Cooldown>
        <Effects>Deals 325 Magic damage and stuns target for 1.75 seconds.</Effects>
        <ExtraEffects></ExtraEffects>
      </Fourth>
    </Ranks>
  </SpellOne>

  <SpellTwo>
    <Name>Aurora</Name>
    <Icon>Images/Spell/Andromeda/Spell2.gif</Icon>
    <Action>Target Position</Action>
    <Description>Andromeda shakes the magnetic field of Newerth, causing an Aurora to erupt, damage, and reduce the armor of all enemies in front of her.</Description>
    <Ranks>
      <First>
        <ManaCost>40</ManaCost>
        <Cooldown>15 Seconds</Cooldown>
        <Effects>Deals 25 damage to targets in a line and applies Aurora for 15 seconds.</Effects>
        <ExtraEffects>-5% Base Damage, -2 Armor</ExtraEffects>
      </First>
      <Second>
        <ManaCost>40</ManaCost>
        <Cooldown>15 Seconds</Cooldown>
        <Effects>Deals 50 damage to targets in a line and applies Aurora for 15 seconds.</Effects>
        <ExtraEffects>-10% Base Damage, -3 Armor</ExtraEffects>
      </Second>
      <Third>
        <ManaCost>40</ManaCost>
        <Cooldown>15 Seconds</Cooldown>
        <Effects>Deals 75 damage to targets in a line and applies Aurora for 15 seconds.</Effects>
        <ExtraEffects>-15% Base Damage, -4 Armor</ExtraEffects>
      </Third>
      <Fourth>
        <ManaCost>40</ManaCost>
        <Cooldown>15 Seconds</Cooldown>
        <Effects>Deals 100 damage to targets in a line and applies Aurora for 15 seconds.</Effects>
        <ExtraEffects>-20% Base Damage, -5 Armor</ExtraEffects>
      </Fourth>
    </Ranks>
  </SpellTwo>
</Andromeda>
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-01-02 17:58:51

一些我认为对你有帮助的东西。

首先,也是最重要的,在处理XML之前设计类。在第一个示例中,将检索到的所有数据元素都粘贴到List<string>中是一条痛苦的道路。你如何找到一个英雄的智慧?通过搜索列表直到找到第11项?列表中的数据并不比XML中的数据更容易访问-我的意思是,在XML中,您至少可以使用XPath找到一些数据。

接下来,如果可以的话,对XML进行结构化,以便在数据和元数据之间有一个清晰的分离。使用

代码语言:javascript
复制
<Hero>
   <Name>Andromeda</Name>

而不是

代码语言:javascript
复制
<Andromeda>

XML ) "Andromeda“是数据(英雄的名字),而不是元数据(指示数据是英雄的标签),b)这样,您就不必担心如何创建带有”损坏的门徒“或”可怜的巫婆“标签的...since元素。

第三,不要在元数据中加入多余的信息。例如,将元素命名为SpellOneSpellTwo等没有什么意义,因为XML中元素的顺序隐式地告诉您哪个是第一个,第二个等等。这使您不必在必须移动对象时重命名它们。如果您需要明确标识哪个拼写是哪个拼写的内容,请使用元素或属性来实现此目的,例如:

最后,实际上已经有了一种将数据从XML文档中提取到对象中的技术。这称为XML反序列化。这看起来有点让人望而生畏(这里有一个非常好的here操作指南),因为为了使用它,您必须了解XML和反射(或者至少是属性)以及它对您的类设计施加的各种限制。但是了解它可以让你从编写大量极其无聊的代码中解脱出来。

票数 1
EN

Stack Overflow用户

发布于 2010-01-02 02:31:59

这里是关于如何使用Linq解析它的开始。关键点是定义一些用于存储信息的类,并根据需要使用各种Linq方法(选择、ToDictionary等)。此外,还可以使用int.Parse或用户定义的函数(请参见parseCooldown)进一步解析某些部分。正则表达式在从结构化文本中提取相关信息时也很方便。

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;

class HeroParseException : ApplicationException
{
    public HeroParseException(string message) : base(message) {}
}

class Spell
{
    public string Name { get; set; }
    public Dictionary<string, SpellAttributes> SpellAttributesByRank { get; set; }
}

class SpellAttributes
{
    public int ManaCost{ get; set; }
    public TimeSpan Cooldown { get; set; }
    public string Effects { get; set; }
}

class Program
{
    static string NameOfHero = "Andromeda";

    static void Main()
    {
        XDocument doc = XDocument.Load("input.xml");
        var spells = doc.Descendants(NameOfHero).Elements().Select(hero => new Spell
        {
            Name = hero.Element("Name").Value,
            SpellAttributesByRank = hero.Element("Ranks").Elements().ToDictionary(
            rank => rank.Name.ToString(),
            rank => new SpellAttributes
            {
                ManaCost = int.Parse(rank.Element("ManaCost").Value),
                Cooldown = parseCooldown(rank.Element("Cooldown").Value),
                Effects = rank.Element("Effects").Value
            })
        });
    }

    private static TimeSpan parseCooldown(string p)
    {
        Match match = Regex.Match(p, @"(\d+)( Seconds)?");
        if (!match.Success)
            throw new HeroParseException("Format for timespan not supported: " + p);
        int number = int.Parse(match.Groups[1].Value);
        return TimeSpan.FromSeconds(number);
    }
}

显然,这里缺少了很多东西,但它应该会给你一个如何进步的想法。

票数 2
EN

Stack Overflow用户

发布于 2010-01-02 01:46:40

我只是猜测了一下,但我认为这就是你想要的。

代码语言:javascript
复制
Action<IEnumerable<XElement>> recurse_elements = null;  
recurse_elements = (elements) =>
{
    foreach (var element in elements)
    {
        Info.Add(element.Value);
        if (element.HasElements)
        {
             recurse_elements(element.Elements());
        }
    }
};

recurse_elements(
    (from hero in HeroInformation.Elements()
     where hero.Element("Name").Value == NameOfHero
     select hero.Elements()).Single()
);

旁注:

重构您的XML是一个好主意。目前,扩展XML将非常具有挑战性。

代码语言:javascript
复制
<Heros>
    <Hero Name="Jim" Age="72" PastTime="Slaying">
        <Spells>
            <Spell Name="Fireball" Damage="1000" Aoe="1000" Description="Kills indiscriminately." />
        </Spells>
    </Hero>
</Heros>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1989119

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档