2

I have the following XML String (XMLText) :

<?xml version="1.0" encoding="utf-8" ?>
<RateSheet>
    <rate category="children" date="2016-04-21">
    <value>1.375</value> 
    </rate>

    <rate category="music" date="2016-05-01">
    <value>2.475</value>                                   
    </rate>
</RateSheet>

I need to read the following information from that XML: category, date und value

I can read category and date - but I can not read the data for value

I have this code:

using (XmlReader reader= XmlReader.Create(new StringReader(XMLText)))
{
    while (reader.ReadToFollowing("rate"))
    {

        Rate rate = new Rate();

        reader.MoveToFirstAttribute();
        rate.Category = reader.Value;  //text of current Node   : Catagory

        //*************************************************************************************

        reader.MoveToNextAttribute();  //text of current Node  : Date
        DateTime myDate;

        if ( DateTime.TryParse( reader.Value, out myDate) )     
        {
         rate.Date =  myDate;                                   
        }

        //*************************************************************************************

        reader.ReadToFollowing("value");   //should be 1.375 or 2.475 - but is always empty ("")

        Console.WriteLine("value Element=" + reader.Value); //test: reader.Value does not the data


        decimal myValue;                                    

        if (Decimal.TryParse(reader.Value, out myValue))
        {
            rate.Value = myValue;
        }
        else
        {
            rate.Value = -1;   // this is what happens because reader.value == ""
        }

        //return collection with result
        myRates.Add(rate);



    }
}
1

3 Answers 3

3

You can do simple Linq to Xml

var myrates = doc.Descendants("rate")
    .Select(r=> new Rate() {
        Category = r.Attribute("category").Value,
        Date =  DateTime.ParseExact(r.Attribute("date").Value,"yyyy-MM-dd", null),
        Value = double.Parse(r.Element("value").Value),

    }).ToList();

Working Demo

Sign up to request clarification or add additional context in comments.

Comments

0

Here is what your code is missing. After

reader.ReadToFollowing("value");

You need to add the following line:

reader.Read();

After that it "reader.Value;" will return text inside <value>. Alternatively instead of linq or Streamreader you can use DOM and xpath:

XmlDocument doc = new XmlDocument();
doc.Load("file.xml");
List<Rate> rates = new List<Rate>();

XmlNodeList nodes = doc.SelectNodes("//rate");

foreach(XmlNode x in nodes)
{
    Rate r = new Rate();
    r.Category = x.Attributes["category"].Value;
    r.Date = DateTime.ParseExact(x.Attributes["date"].Value,"yyyy-MM-dd", null)x.Attributes["category"].Value;
    r.Value = double.Parse(x.SelectSingleNode("./value").InnerText));
    rates.Add(r);
}

Comments

0

I like using a combination of XmlReader and Linq

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

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            string XMLText = File.ReadAllText(FILENAME);
            List<Rate> myRates = new List<Rate>(); 

            using (XmlReader reader = XmlReader.Create(new StringReader(XMLText)))
            {
                while (!reader.EOF)
                {
                    if (reader.Name != "rate")
                    {
                        reader.ReadToFollowing("rate");
                    }
                    if(!reader.EOF)
                    {
                        XElement xRate = (XElement)XElement.ReadFrom(reader);
                        Rate rate = new Rate();

                        rate.Category = xRate.Attribute("category").Value;  //text of current Node   : Catagory

                        DateTime myDate;

                        if (DateTime.TryParse(xRate.Attribute("date").Value, out myDate))
                        {
                            rate.Date = myDate;
                        }


                        Console.WriteLine("value Element=" + xRate.Element("value").Value); //test: reader.Value does not the data


                        decimal myValue;

                        if (Decimal.TryParse(xRate.Element("value").Value, out myValue))
                        {
                            rate.Value = myValue;
                        }
                        else
                        {
                            rate.Value = -1;   // this is what happens because reader.value == ""
                        }

                        //return collection with result
                        myRates.Add(rate);

                    }
                }
            }
        }
        public class Rate
        {
            public DateTime Date { get; set; }
            public decimal Value { get; set; }
            public string Category { get; set; }
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.