3

I'm trying to parse XML string into list, result count is always zero.

 string result = "";
            string address = "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";

            // Create the web request  
            HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;

            // Get response  
            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                // Get the response stream  
                StreamReader reader = new StreamReader(response.GetResponseStream());

                // Read the whole contents and return as a string  
                result = reader.ReadToEnd();
            }

            XDocument doc = XDocument.Parse(result);

            var ListCurr = doc.Descendants("Cube").Select(curr => new CurrencyType() 
                    { Name = curr.Element("currency").Value, Value = float.Parse(curr.Element("rate").Value) }).ToList();

where I'm going wrong.

2
  • @BassamAlugili: It's really not a duplicate of that. Commented Sep 7, 2013 at 8:26
  • @Manish I have remove it and vote to you! When Jon answer a question then that must be a good question! thanks! Commented Sep 7, 2013 at 19:59

2 Answers 2

5

The problem is that you're looking for elements without a namespace, whereas the XML contains this in the root element:

xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"

That specifies the default namespace for any element. Also, currency and rate are attributes within the Cube elements - they're not subelements.

So you want something like:

XNamespace ns = "http://www.ecb.int/vocabulary/2002-08-01/eurofxref";
var currencies = doc.Descendants(ns + "Cube")
                    .Select(c => new CurrencyType {
                                     Name = (string) c.Attribute("currency"),
                                     Value = (decimal) c.Attribute("rate")
                                 })
                    .ToList(); 

Note that because I'm casting the currency attribute to string, you'll end up with a null Name property for any currencies which don't specify that attribute. If you want to skip those elements, you can do so with a Where clause either before or after the Select.

Also note that I've changed the type of Value to decimal rather than float - you shouldn't use float for currency-related values. (See this question for more details.)

Additionally, you should consider using XDocument.Load to load the XML:

XDocument doc = XDocument.Load(address);

Then there's no need to create the WebRequest etc yourself.

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

2 Comments

Thanks for letting me know about XDocument doc = XDocument.Load(address);
@Manish: I've now edited it to use decimal rather than float - and please see my comment on the answer that you've accepted, as that won't work as-is if the current thread culture uses , as a decimal separator.
2
XDocument doc = XDocument.Parse(result);
XNamespace ns = "http://www.ecb.int/vocabulary/2002-08-01/eurofxref";

var ListCurr = doc.Descendants(ns + "Cube")
                    .Where(c=>c.Attribute("currency")!=null) //<-- Some "Cube"s do not have currency attr.
                    .Select(curr => new CurrencyType  
                    { 
                        Name = curr.Attribute("currency").Value, 
                        Value = float.Parse(curr.Attribute("rate").Value) 
                    })
                    .ToList();

2 Comments

It would be good to actually explain what the problem was rather than just posting the code. I'd also recommend using the cast rather than float.Parse - this code will fail in cultures which use comma as a decimal separator.
@JonSkeet You are right, but you've already explained it very well.

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.