2

I want to get the specific node from my XML response using Linq My Xml:

<DataSet xmlns="http://www.bnr.ro/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bnr.ro/xsd nbrfxrates.xsd">
    <Header>
        <Publisher>National Bank of Romania</Publisher>
        <PublishingDate>2016-12-30</PublishingDate>
        <MessageType>DR</MessageType>
    </Header>
    <Body>
        <Subject>Reference rates</Subject>
        <OrigCurrency>RON</OrigCurrency>
        <Cube date="2016-01-04">
            <Rate currency="AED">1.1272</Rate>
            <Rate currency="EUR">4.5169</Rate>
            <Rate currency="BGN">2.3094</Rate>
            <Rate currency="HUF" multiplier="100">1.4320</Rate>
            <Rate currency="INR">0.0622</Rate>
            <Rate currency="JPY" multiplier="100">3.4798</Rate>
            <Rate currency="KRW" multiplier="100">0.3481</Rate>
            <Rate currency="MDL">0.2107</Rate>
        </Cube>
        <Cube>
        ...
        </Cube>
    </Body>
</DataSet>

So i want to position on the cube which have date equals with a date paramater. Then i want to gate the rate value which has currency equals with "EUR". I am trying to do this with Linq but it's not working My Linq code:

 WebClient webClient = new WebClient();
 string url = "http://www.bnr.ro/files/xml/years/nbrfxrates" + year + ".xml";
 HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
 HttpWebResponse response = request.GetResponse() as HttpWebResponse;

 XDocument systemXml = XDocument.Load(response.GetResponseStream());

 XElement cube = (from cubeElement in systemXml.Elements("Cube")
                 where cubeElement.Attribute("date").ToString().Equals(data)
                 select cubeElement).Single();

 XElement rate = (from rateElement in cube.Elements("Rate")
                  where rateElement.Attribute("currency").ToString().Equals("EUR")
                  select rateElement).Single();

My problem is that systemXml.Elements("Cube") returns null. This is my url for web request http://www.bnr.ro/files/xml/years/nbrfxrates2017.xml

Chuck Savage
  • 11,775
  • 6
  • 49
  • 69
S.over17
  • 199
  • 2
  • 2
  • 14
  • Possible duplicate of [Finding element in XDocument?](http://stackoverflow.com/questions/8460464/finding-element-in-xdocument), or [Query an XDocument for elements by name at any depth](http://stackoverflow.com/questions/566167/query-an-xdocument-for-elements-by-name-at-any-depth) or [What is the difference between Linq to XML Descendants and Elements](http://stackoverflow.com/questions/3705020/what-is-the-difference-between-linq-to-xml-descendants-and-elements) – NP3 May 11 '17 at 16:11
  • @NemanjaPerovic ok, i see, but i have a problem with that null :(, sorry if i wrote bad.. – S.over17 May 11 '17 at 16:13
  • No problem. Try Descendants instead of Elements. To see why, look a the documentation, or the links I added – NP3 May 11 '17 at 16:13
  • Your XML file is not well-formatted you are missing a lot of closing tags. Correct it so that we will be able to help you – Samvel Petrosov May 11 '17 at 16:18
  • @S.Petrosov http://www.bnr.ro/files/xml/years/nbrfxrates2017.xml, here is my entire xml file – S.over17 May 11 '17 at 16:21
  • Have you tried using Descendants instead of Elements? – NP3 May 11 '17 at 17:50

2 Answers2

1

It looks like you need the namespace.

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

namespace ConsoleApplication55
{
    class Program
    {
        static void Main(string[] args)
        {
            string url = "http://www.bnr.ro/files/xml/years/nbrfxrates2017.xml";

            XDocument systemXml = XDocument.Load(url);
            XNamespace ns = ((XElement)systemXml.FirstNode).GetDefaultNamespace();

            DateTime date = DateTime.Parse("2017-01-05");
            var results = systemXml.Descendants(ns + "Cube")
                .Where(x => ((DateTime)x.Attribute("date") == date))
                .Descendants(ns + "Rate")
                .Where(x => (string)x.Attribute("currency") == "EUR")
                .FirstOrDefault();
            var value = (decimal)results;

        }
    }

}
Chuck Savage
  • 11,775
  • 6
  • 49
  • 69
jdweng
  • 33,250
  • 2
  • 15
  • 20
0

Your Root element is DataSet,which has childs and one of them is Body,which has childs Cube. Also you need to specify the namespace of the element which is {http://www.bnr.ro/xsd}. So here is working LINQ for you.

       XDocument systemXml = XDocument.Load(path);

        XElement cube = (from cubeElement in systemXml.Elements("{http://www.bnr.ro/xsd}DataSet").Elements("{http://www.bnr.ro/xsd}Body").Elements("{http://www.bnr.ro/xsd}Cube")
                             where cubeElement.Attribute("date").Value.Equals("2017-01-03")
                         select cubeElement).Single();

        XElement rate = (from rateElement in cube.Elements("{http://www.bnr.ro/xsd}Rate")
                         where rateElement.Attribute("currency").Value.Equals("EUR")
                         select rateElement).Single();

Enjoy it!!

Samvel Petrosov
  • 7,580
  • 2
  • 22
  • 46