LINQ/XDocument, konwersja typów

0

Witam

Dopiero niedawno zacząłem przygodę z C# .NET. Przyznaje, że się pogubiłem w buszu manuali i informacji.

Problem wygląda następująco:

Mój skrypt PHP produkuje takiego XML:

 
<?xml version="1.0" encoding="UTF-8" ?> 
- <StockCollection>
- <Stocks>
- <Stock>
  <Ticker>ABR</Ticker> 
  <Exchange>NYSE</Exchange> 
  <Issue_name>Arbor Realty Trust Common Stock</Issue_name> 
  <Type>Common Stock</Type> 
  <Sector>Financial</Sector> 
  <Avg_volume>83370</Avg_volume> 
  <Last_price>5.37</Last_price> 
  </Stock>
- <Stock>
  <Ticker>ABTL</Ticker> 
  <Exchange>NASDAQ-GM</Exchange> 
  <Issue_name>Autobytel Inc. - Common Stock</Issue_name> 
  <Type>Common Stock</Type> 
  <Sector>Technology</Sector> 
  <Avg_volume>143034</Avg_volume> 
  <Last_price>0.78</Last_price> 
  </Stock> 
</Stocks>
 </StockCollection> 

Klasy wyglądają tak:

  public class Stock
    {
      [XmlElement("Ticker")]
       public string Ticker;

        [XmlElement("Exchange")]
       public string Exchange;

        [XmlElement("Issue_name")]
       public string Issue_name;

        [XmlElement("Type")]
       public string Type;

        [XmlElement("Sector")]
       public string Sector;

        [XmlElement("Avg_volume")]
       public int Avg_volume;

        [XmlElement("Last_price")]
       public decimal Last_price

        [XmlElement("Earnings_date")]
        public string Earnings_date;

    }

    public class StockCollection
    {
        [XmlArray("Stocks")]
        [XmlArrayItem("Stock")]
        public Stock[] Stocks;
    }

Pobieranie danych odbywa się:

  public void Get()
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(_url);
            req.Proxy = null;
            req.Timeout = 6500;
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            StreamReader sr = new StreamReader(resp.GetResponseStream());
            XStockData = XDocument.Load(sr);

Takie załadowanie XML do dataGrid działa w porządku:

  var result = from c in md.XStockData.Descendants("Stock")
                         select new 
                         {

                            Ticker= c.Element("Ticker").Value,
                              Exchange = c.Element("Exchange").Value,
                              Issue_name = c.Element("Issue_name").Value,
                              Type = c.Element("Type").Value,
                              Sector = c.Element("Sector").Value,
                              Avg_volume = c.Element("Avg_volume").Value,
                              Last_price = c.Element("Last_price").Value,

                         };
            dataGrid.DataSource = result.ToList();

Natomiast jeśli chce to zrobić jawnie za pomocą klasy Stock tj:

    var result = from c in md.XStockData.Descendants("Stock")
                        
                         select new Stock
                         {

                            Ticker= c.Element("Ticker").Value,
                              Exchange = c.Element("Exchange").Value,
                              Issue_name = c.Element("Issue_name").Value,
                              Type = c.Element("Type").Value,
                              Sector = c.Element("Sector").Value,
                              Avg_volume = int.Parse(c.Element("Avg_volume").Value), # dodane Parse
                              Last_price = decimal.Parse(c.Element("Last_price").Value), # dodane Parse

                         };

kompilator się wysypuje: "Input string is not in correct format" i podkreśla całe zapytanie SELECT.

Jak mam zmusić XDocument albo cokolwiek ;-) żeby avg_volume był traktowany jako INT a last_price jako DECIMAL ?

Dzięki
dawid

0

.NET jest taki sprytny, że programy w nim napisane korzystają z ustawień regionalnych systemu.
W Polsce separatorem dziesiętnym jest przecinek, więc metoda decimal.Parse oczekuje, że ciąg znaków których chcesz sparsować będzie zawierał przecinek. Tymczasem w Twoich danych źródłowych:

<Last_price>5.37</Last_price>

jest kropka.

Rozwiązanie jest bardzo proste, trzeba użyć przeciążonej wersji metody Parse, która pozwala na (upraszczając) zignorowanie ustawień regionalnych:

 Last_price = decimal.Parse(c.Element("Last_price").Value, CultureInfo.InvariantCulture)
0

Zainteresuj się tematem "xml serialization", bo większość z tego co próbujesz zrobić, może być wykonana automatycznie.

0

Właśnie jeśli chce to zrobić via XMLSerializer:

 public static StockCollection GetInPlayData()
        {
            XmlSerializer xs = new XmlSerializer(typeof(StockCollection));

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(_url);
            req.Proxy = null;
            req.Timeout = 6500;
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            return (StockCollection)xs.Deserialize(new StreamReader(resp.GetResponseStream()));

        } 

nie wiem jak podpiąć tą kolekcje pod datagrid.DataSource:

// Tak ładuje puste Rows`y - bez danych z sc.Stocks
   StockCollection sc = marketData.GetInPlayData();
   dataGrid.DataSource = sc.Stocks.ToList()

Pod dataGrid będzie znajdował się layout z możliwością filtracji danych. Co chce zrobić to odpytywać XML lub jakikolwiek obiekt i filtrować dane w tabelce. Póki co wpadłem na pomysł XDocument i LINQ(klauzule where, group itp) . Z braku wiedzy nie wiem jak mam przefiltrować np taki obiekt StockCollection.Stocks[Stock].

Dzięki za pomoc.
dawid

0

Może ma ktoś pomysł jak mój obiekt ustawić jako dgv.DataSource ? Próbowałem już na pare sposobów i zawsze mi dodaje poprawną ilość rows`ów ale bez danych - dodaje puste rowsy.
W kolumnach DataGridView DataPropertyName mam ustawione na dokładnie takie same nazwy jak w klasie Stock.

np:

  
StockCollection sc = marketData.GetInPlayData();
            BindingList<Stock> list = new BindingList<Stock>(sc.Stocks.ToList());
            dataGrid.AutoGenerateColumns = false;
            dataGrid.DataSource = list;
0

okej już zrozumiałem - choć myślałem wcześniej że rozumiem - akcesory get i set. Działający kod:

 
public class Stock
    {
       [XmlElement("Ticker")]
       public string Ticker { get; set; }

        [XmlElement("Exchange")]
       public string Exchange { get; set; }

        [XmlElement("Issue_name")]
        public string Issue_name { get; set; }

        [XmlElement("Type")]
        public string Type { get; set; }

        [XmlElement("Sector")]
        public string Sector { get; set; }

        [XmlElement("Avg_volume")]
        public int Avg_volume { get; set; }

        [XmlElement("Last_price")]
        public decimal Last_price { get; set; }

        [XmlElement("Earnings_date")]
        public string Earnings_date { get; set; }

    }

i DataSource:

 
            StockCollection sc = marketData.GetInPlayData();
                    
            dataGrid.AutoGenerateColumns = false;
            dataGrid.DataSource = sc.Stocks.ToList();

1 użytkowników online, w tym zalogowanych: 0, gości: 1