【问题标题】:C# use Linq to pull data from xmlC# 使用 Linq 从 xml 中提取数据
【发布时间】:2016-05-18 09:13:22
【问题描述】:

我在使用 Linq 构建包含 XML 数据的对象时遇到问题。例如,我在 url http://api.eve-central.com/api/marketstat?typeid=34&usesystem=30000142 中有 XML 数据。在MarketStat 类中我想持有type id 值,在MarketValue 类数组中我想持有volume avg max min stddev median percentilevalues sellall 节点。到目前为止我从未使用过 linq,所以请帮助我在下面的代码中解决我的问题:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    internal class MarketValue
    {
        public int Volume { get; set; }
        public double Avg { get; set; }
        public double Max { get; set; }
        public double Min { get; set; }
        public double Stddev { get; set; }
        public double Median { get; set; }
        public double Percentile { get; set; }
    }
    internal class MarketStat
    {
        public string Name { get; set; }
        public MarketValue[] MarketValueses { get; set; }
    }
    internal class Program
    {
        private static List<MarketStat> list;
        internal static void Main(string[] args)
        {
            list = (
                from e in XDocument.Load("http://api.eve-central.com/api/marketstat?typeid=34&usesystem=30000142").
                    Root.Elements("marketstat")
                select new MarketStat
                {
                    Name = (string) e.Element("type id"),
                    MarketValueses = (
                        from mv in e.Elements("buy")
                        select new MarketValue
                        {
                            Volume = (int) mv.Element("volume"),
                            Avg = (double) mv.Element("avg"),
                            Max = (double)mv.Element("max"),
                            Min = (double)mv.Element("min"),
                            Stddev = (double)mv.Element("stddev"),
                            Median = (double)mv.Element("median"),
                            Percentile = (double)mv.Element("percentile")
                        }).ToArray()
               }).ToList();
         }
    }
}

【问题讨论】:

  • 您的链接只带回一组数字,而不是任何 XML。也许这个 QA 可以帮助你:stackoverflow.com/questions/10518372/…
  • @John,它返回 XML;可能您的浏览器只是将其视为 HTML 而不是原始显示。
  • 好的,请注意。我认为提到的 QA 将有助于序列化对象。

标签: c# arrays linq


【解决方案1】:

您当前代码的问题是您想要获取 type 元素的 id 属性,但您尝试使用 type id 获取它,这是错误的。此外,您在三个节点(即 buy、sell 和 all 中具有 MarketValue 的值,但目前您仅从 buy 节点获取详细信息。

这应该会给你预期的输出:-

XDocument xdoc = XDocument.Load("http://api.eve-central.c...
var result = xdoc.Root.Elements("type")
                 .Select(ms => new MarketStat
                    {
                        Name = (string)ms.Attribute("id"),
                        MarketValueses = ms.Elements()
                                      .Select(mv => new MarketValue
                                         {
                                             Volume = (long)mv.Element("volume"),
                                             Avg = (double)mv.Element("avg"),
                                             Max = (double)mv.Element("max"),
                                             Min = (double)mv.Element("min"),
                                             Stddev = (double)mv.Element("stddev"),
                                             Median = (double)mv.Element("median"),
                                             Percentile = (double)mv.Element("percentile")
                                         }).ToArray()
                             }).ToList();

【讨论】:

  • 代码给我一个空result列表的错误。当我将Root.Elements("marketstat").Select(ms =&gt; new MarketStatName = (string) ms.Element("type").Attribute("id") 一起使用时,它适用于type id 节点,但应该保存buy sell all 的数组给我一个错误。请为我再次检查代码。
  • @user5671675 - 是的,那是因为现在你有evec_api 作为根节点,所以这条线失败了xdoc.Root.Elements("type")。为了遍历 XML,您需要告诉 type 节点存在于 marketstat 节点中,因此您的代码应该是:- xdoc.Root.Element("marketstat").Elements("type") 或 Else 您可以直接获取所有 type 这样的节点:- xdoc.Descendants("type").Select...
  • 谢谢。现在我知道我的问题出在哪里了,我将继续练习并提高 XML 文档的技能。
【解决方案2】:

您正在寻找一个名为“type id”的元素。这不是 XML 中元素的有效名称。您应该只查找名为 type 的元素...这是该元素的名称:

<type id="34">

如果您想按 ID 过滤,则可以获取 属性 id

您还尝试直接从 marketstat 元素中获取 buy 元素 - 它不存在;它在type 元素内。基本上你需要多注意XML的结构。

我的猜测是,您也应该只期望一个 buy 元素 - 这让事情变得更简单。我怀疑您不需要在结果的每个元素中都包含一个数组...

【讨论】:

    【解决方案3】:

    您的 xml 解析有一些问题。

    首先你不能像这里那样调用类型 id

    Name = (string) e.Element("type id")
    

    id 是 type 元素的一个属性,所以你必须做这样的事情

    Name = e.Element("type").Attributes("id").Value
    

    另一个问题是您尝试迭代购买值的部分。 你有以下行

    from mv in e.Elements("buy")
    

    这不起作用,因为 e 是文档根元素。 buy 是 type 元素的子元素,所以你会想要这样的东西

    from mv in e.Elements("type").Descendants("buy")
    

    希望这对您有所帮助并为您指明正确的方向

    这是一个工作示例

    list = (
        from e in XDocument.Load("http://api.eve-central.com/api/marketstat?typeid=34&usesystem=30000142").
            Root.Elements("marketstat")
            let type = e.Element("type")
        select new MarketStat
        {
            Name = type.Attribute("id").Value,
            MarketValueses = (
                from mv in type.Descendants("buy")
                select new MarketValue
                {
                    Volume = long.Parse(mv.Element("volume").Value),
                    Avg = double.Parse(mv.Element("avg").Value),
                    Max = double.Parse(mv.Element("max").Value),
                    Min = double.Parse(mv.Element("min").Value),
                    Stddev = double.Parse(mv.Element("stddev").Value),
                    Median = double.Parse(mv.Element("median").Value),
                    Percentile = double.Parse(mv.Element("percentile").Value)
                }).ToArray()
        }).ToList();
    

    ** 附带说明一下,在解析该 xml 时,volume 值太大而无法放入 int32 值,因此我将其更改为 long

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 1970-01-01
      相关资源
      最近更新 更多