【问题标题】:How to get element value and assign it to a Double using linq to xml?如何使用 linq to xml 获取元素值并将其分配给 Double?
【发布时间】:2016-10-20 16:44:27
【问题描述】:

我需要从以下 xml 中获取所有 3 个“avg”值的值,然后将它们分配给一个双精度数组。使用 linq 到 xml。我是 linq to xml 的新手,所以我不太确定该怎么做。

这是我当前的代码

var q = from e in xDoc.Descendants("sell")
        select new
        {
            result = e.Element("avg").Value
        };

XML:

<?xml version='1.0' encoding='utf-8'?>
<evec_api version="2.0" method="marketstat_xml">
    <marketstat>
        <type id="626">
            <buy>
                <volume>11</volume>
                <avg>9345454.55</avg>
                <max>11500000.00</max>
                <min>7500000.00</min>
                <stddev>1862495.34</stddev>
                <median>7600000.00</median>
                <percentile>11500000.00</percentile>
            </buy>
            <sell>
                <volume>23</volume>
                <avg>18749987.25</avg>
                <max>18749987.25</max>
                <min>18749987.25</min>
                <stddev>0.00</stddev>
                <median>18749987.25</median>
                <percentile>18749987.25</percentile>
            </sell>
            <all>
                <volume>34</volume>
                <avg>15707344.32</avg>
                <max>18749987.25</max>
                <min>7500000.00</min>
                <stddev>4573474.77</stddev>
                <median>18749987.25</median>
                <percentile>7500000.00</percentile>
            </all>
        </type>
    </marketstat>
</evec_api>

【问题讨论】:

  • 您想知道他们每个人的出处还是一个简单的double[] 结果?还请提供您已经尝试过的操作。 linq to xml上有很多例子
  • 顺便说一句,你得到的反对票可能是因为当你发布问题时你没有解释你尝试了什么。您刚刚说“我需要 X”.. 这不是 SO 的工作方式。您必须付出一些努力,我们可以从那里提供帮助
  • @GiladGreen 谢谢,我会在以后的问题中记住这一点

标签: c# xml linq linq-to-xml


【解决方案1】:

这些答案看起来非常冗长。如果您想要三个 avg 值,并且只有标签 &lt;marketstat&gt;&lt;type id="626"&gt; 中的值,但如果您想避免更多的 marketstat 和类型,则必须深入挖掘。

double[] averages = xDoc.Descendants("avg")
                        .Select(xavg => (double)xavg)
                        .ToArray();

例如,

XElement type626 = xDoc.Descendants("type")
                       .First(x => (int)x.Attribute("id") == 626);

然后将前面的粘贴到这里,我们将xDoc替换为type626

double[] averages = type626.Descendants("avg")
                        .Select(xavg => (double)xavg)
                        .ToArray();

【讨论】:

    【解决方案2】:
    using System;
    using System.Linq;
    using System.Xml.Linq;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main()
            {
                var xml = @"<?xml version='1.0' encoding='utf-8'?>
    <evec_api version=""2.0"" method=""marketstat_xml"">
        <marketstat>
            <type id=""626"">
                <buy>
                    <volume>11</volume>
                    <avg>9345454.55</avg>
                    <max>11500000.00</max>
                    <min>7500000.00</min>
                    <stddev>1862495.34</stddev>
                    <median>7600000.00</median>
                    <percentile>11500000.00</percentile>
                </buy>
                <sell>
                    <volume>23</volume>
                    <avg>18749987.25</avg>
                    <max>18749987.25</max>
                    <min>18749987.25</min>
                    <stddev>0.00</stddev>
                    <median>18749987.25</median>
                    <percentile>18749987.25</percentile>
                </sell>
                <all>
                    <volume>34</volume>
                    <avg>15707344.32</avg>
                    <max>18749987.25</max>
                    <min>7500000.00</min>
                    <stddev>4573474.77</stddev>
                    <median>18749987.25</median>
                    <percentile>7500000.00</percentile>
                </all>
            </type>
        </marketstat>
    </evec_api>";
    
                var xdoc = XDocument.Parse(xml);
                var typeElement = xdoc.Element("evec_api").Element("marketstat").Element("type");
                var avgElements = typeElement.Elements().Select(e => e.Element("avg"));
    
                foreach (var avgElement in avgElements)
                    Console.WriteLine(avgElement.Value);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      在 VB .Net 中我会这样做

          Dim avgs() As Double = xe...<avg>.Select(Function(a) CDbl(a.Value)).ToArray
      

      在 C# 中看起来像这样(根据我使用的转换器)

      double[] avgs = xe.Select(a => Convert.ToDouble(a.Value)).ToArray;
      

      经过测试

          Dim xe As XElement
          'to load from a file
          '  xe = XElement.Load("Your Path Here")
      
          ' for testing
          xe = <evec_api version="2.0" method="marketstat_xml">
                   <marketstat>
                       <type id="626">
                           <buy>
                               <volume>11</volume>
                               <avg>9345454.55</avg>
                               <max>11500000.00</max>
                               <min>7500000.00</min>
                               <stddev>1862495.34</stddev>
                               <median>7600000.00</median>
                               <percentile>11500000.00</percentile>
                           </buy>
                           <sell>
                               <volume>23</volume>
                               <avg>18749987.25</avg>
                               <max>18749987.25</max>
                               <min>18749987.25</min>
                               <stddev>0.00</stddev>
                               <median>18749987.25</median>
                               <percentile>18749987.25</percentile>
                           </sell>
                           <all>
                               <volume>34</volume>
                               <avg>15707344.32</avg>
                               <max>18749987.25</max>
                               <min>7500000.00</min>
                               <stddev>4573474.77</stddev>
                               <median>18749987.25</median>
                               <percentile>7500000.00</percentile>
                           </all>
                       </type>
                   </marketstat>
               </evec_api>
      

      【讨论】:

        【解决方案4】:

        您上面的代码的问题是您只检索avgs 之一的值。使用Descendants可以找到所有avgs,然后获取值:

        var result = xDoc.Descendants("avg").Select(e => (double)e);
        

        如果您想确定它是 double 并且不会失败并且 InvalidCast,请使用 double.TryParse请记住,使用 value 会产生副作用。如果您不想这样做,您可以将TryParse 用于where,然后在select 中再次使用Parse

        double value = 0;
        var result = (from element in xDoc.Descendants("avg")
                      where double.TryParse(element.Value, out value)
                      select value).ToList();
        
        // result: 9345454.55, 18749987.25, 15707344.32
        

        如果您希望结果在数字和它的来源之间也有一些暗杀,您可以使用.Parent 属性:

        double value = 0;
        var result = (from element in xDoc.Descendants("avg")
                      where  double.TryParse(element.Value, out value)
                      select new
                      {
                          Tag = element.Parent.Name.LocalName,
                          Value = value
                      }).ToList();
        

        【讨论】:

        • 这似乎只返回最后一个值。
        • 抱歉,这是我用来返回值的代码:Output.Text = Convert.ToString(getResultPrices.value);
        • @Antono - 我在发布之前对其进行了测试。请再次检查
        • 不,查看 values 结果返回的计数为 3,但是 value 只返回最后一个平均值
        • 谢谢,我只是将value 分配给文本框,而不是result
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-23
        • 1970-01-01
        相关资源
        最近更新 更多