1

Using this URL from European Central Bank:

www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml

I would like to import the currency symbol and rate into a Dictionary or object. I've got it reading into an xml doc but I'm having trouble picking out the node attributes.

Thanks

string xmlString;
        using (var client = new WebClient())
        {
            xmlString = client.DownloadString("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
        }

        var xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(xmlString);

        foreach(XmlNode node  in xmlDoc.SelectNodes("//*/Cube/@currency"))
        {
            // add currency and rate to dictionary
        }
J Benjamin
  • 4,722
  • 6
  • 29
  • 39

4 Answers4

6

I think the issue is with your xPath selector.

A value of "//*[@currency]" will select all elements with an attribute of "currency"

class Program
{
    public static void Main(string[] args)
    {
        List<Rate> rates = new List<Rate>();

        var doc = new XmlDocument();
        doc.Load(@"http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");

        XmlNodeList nodes = doc.SelectNodes("//*[@currency]");

        if (nodes != null)
        {
            foreach (XmlNode node in nodes)
            {
                var rate = new Rate()
                           {
                              Currency = node.Attributes["currency"].Value,
                              Value = Decimal.Parse(node.Attributes["rate"].Value, NumberStyles.Any, new CultureInfo("en-Us"))
                           };
                rates.Add(rate);
            }
        }
    }
}
class Rate
{
    public string Currency { get; set; }
    public decimal Value { get; set; }
}
STLDev
  • 5,950
  • 25
  • 36
2

If the XPath expression does not include a prefix, it is assumed that the namespace URI is the empty namespace. If your XML includes a default namespace, you must still add a prefix and namespace URI to the XmlNamespaceManager; otherwise, you will not get any nodes selected.

Use this overload XmlNode.SelectNodes(String, XmlNamespaceManager).

XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ecb", "http://www.ecb.int/vocabulary/2002-08-01/eurofxref");
foreach (XmlNode node in xmlDoc.SelectNodes("//ecb:Cube[@currency]", nsmgr))
kennyzx
  • 12,845
  • 6
  • 39
  • 83
1
        string xmlString;
        using (var client = new WebClient())
        {
            xmlString = client.DownloadString("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
        }

    var doc = XDocument.Parse(xmlString);
    XNamespace ns = "http://www.ecb.int/vocabulary/2002-08-01/eurofxref";
    var values = doc
        .Root
        .Element(ns + "Cube")             
        .Element(ns + "Cube")
        .Elements(ns + "Cube")
        .ToDictionary(e => e.Attribute("currency"), e => (double) e.Attribute("rate"));
Jay Allard
  • 938
  • 6
  • 12
0
class Program
{
    static void Main(string[] args)
    {
        List<Rate> rates = new List<Rate>();

        var doc = new XmlDocument();
        doc.Load(@"http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");

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

        for (int i = 0; i < nodes.Count; i++)
        {
            var rate = new Rate()
            {
                Currency = nodes[i].Attributes[0].Value,
                Value = Decimal.Parse(nodes[i].Attributes[1].Value)
            };

            rates.Add(rate);
        }
        Console.WriteLine();
    }
}

class Rate
{
    public string Currency { get; set; }
    public decimal Value { get; set; }
}
J Benjamin
  • 4,722
  • 6
  • 29
  • 39
  • Do I need to wrap the document load in "using"? – J Benjamin Jun 26 '18 at 03:26
  • no you don’t, since there is nothing to dispose of. The problem you are experiencing is caused by the default xml namespace in the document. Your solution is somewhat loose that you pick whatever nodes at the fourth level without checking its name and attribute. – kennyzx Jun 26 '18 at 04:49
  • You cannot use a `using` statement when creating the XML document because it does not have an `IDisposable` interface. – STLDev Jun 26 '18 at 06:52