2

I'm trying to parse the following XML structure in C#. I want to create an List> with the currencies.

<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"   xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
  <Cube time="2013-09-27">
    <Cube currency="USD" rate="1.3537"/>
    <Cube currency="JPY" rate="133.28"/>
    <Cube currency="BGN" rate="1.9558"/>
    <Cube currency="CZK" rate="25.690"/>
    <Cube currency="DKK" rate="7.4573"/>
    (....)

I've tried using XDocument.Descendants, but it's not returning anything. I'm guessing it has to do with the fact that the Cube-element is used in several levels.

XDocument xdoc = XDocument.Parse(xml);
var currencies = from cube in xdoc.Descendants("Cube")
                    select new
                        {
                            Currency = cube.Attribute("currency").Value,
                            Rate = cube.Attribute("rate").Value
                        };

foreach (var currency in currencies)
    this.Add(new KeyValuePair<string, double>(currency.Currency, Convert.ToDouble(currency.Rate)));

How can I parse the XML structure to get the currencies?

1
  • had the same problem with exactly the same file from ECB :) Thanks a lot to @L.B - works fine Commented Feb 22, 2016 at 8:48

3 Answers 3

3

You have two problems with your code

  • Every Cube doesn't have currency and rate attribute
  • You ignore the Xml namespace

Since it seems you want to create a dictionary according to your code:

XNamespace ns = "http://www.ecb.int/vocabulary/2002-08-01/eurofxref";
var xDoc = XDocument.Load(fname);

var dict = xDoc.Descendants(ns + "Cube")
               .Where(cube => cube.Attributes().Any(a => a.Name == "currency"))
               .ToDictionary(cube => cube.Attribute("currency").Value,
                             cube => (decimal)cube.Attribute("rate"));

PS: You don't have to parse the rate explicitly. It can be done while reading the xml by casting

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

Comments

1

Try xdoc.XPathSelectElements("//Cube/Cube/Cube[@name='currency']")

Comments

1

You have to add a namespace (the Cube elements are not in the default empty namespace) and you have to check if the Cube element has indeed the currency attribute.

This is the closest solution to your curent code that will work:

XDocument xdoc = XDocument.Parse(xml);
XNamespace nsSys = "http://www.ecb.int/vocabulary/2002-08-01/eurofxref";

var currencies = from cube in xdoc.Descendants(nsSys+ "Cube")
                 where cube.Attribute("currency") !=null
                 select new
                 {
                      Currency = cube.Attribute("currency").Value,
                      Rate = cube.Attribute("rate").Value
                 };

Used this Answer as reference

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.