Spacewalker
Spacewalker

Reputation: 571

Can not read certain element from XML string

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



    }
}

Upvotes: 2

Views: 1252

Answers (3)

jdweng
jdweng

Reputation: 34421

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; }
        }
    }
}

Upvotes: 0

Kent Kostelac
Kent Kostelac

Reputation: 2466

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

Upvotes: 0

Hari Prasad
Hari Prasad

Reputation: 16956

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

Upvotes: 3

Related Questions