user5671675 February 2016

C# use Linq to pull data from xml

I have problem with building object holding XML data using Linq. For example, I have XML data in url http://api.eve-central.com/api/marketstat?typeid=34&usesystem=30000142 . In MarketStat class I want to hold type id value and in MarketValue class array I want to hold volume avg max min stddev median percentilevalues of buy sell all nodes. I have never used linq so far so please help me fix my problem in code below:

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"),
               

Answers


Rahul Singh February 2016

The problem with your current code is that you want to fetch the id attribute of type element but you are trying to fetch it with type id which is wrong. Also you have the values of MarketValue in three nodes i.e. buy,sell & all but currently you are fetching details from just buy node.

This should give you the expected output:-

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();


Jon Skeet February 2016

You're looking for an element called "type id". That's not a valid name for an element in XML. You should just look for elements called type... that's the name of this element:

<type id="34">

If you want to filter by ID, you could then fetch the attribute id.

You're also trying to fetch the buy element directly from the marketstat element - it isn't there; it's within the type element. You need to pay more attention to the structure of the XML, basically.

My guess is that you should only expect a single buy element, too - which makes things simpler. I suspect you don't need an array within each element of your results...


bhmahler February 2016

You have a few things wrong with your xml parsing.

first of all you can't call type id as you do here

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

id is an attribute of the type element so you would have to do something like this

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

Another issue is in the section where you are trying to iterate the buy values. you have the following line

from mv in e.Elements("buy")

This will not work because e is the document root element. buy is a child of the type element so you would want something like this

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

Hope this helps and points you in the right direction

Here is a working example

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();

** On a side note, when parsing that xml, the volume value was too large to fit into an int32 value so I changed it to a long

Post Status

Asked in February 2016
Viewed 2,351 times
Voted 9
Answered 3 times

Search




Leave an answer