user3210063
user3210063

Reputation: 11

find element in xml, and take other element value

My xml look like:

<CURRENCIES>
 <LAST_UPDATE>2014-01-17</LAST_UPDATE>
 <CURRENCY>
   <NAME>Dollar</NAME>
   <UNIT>1</UNIT>
   <CURRENCYCODE>USD</CURRENCYCODE>
   <COUNTRY>USA</COUNTRY>
   <RATE>3.489</RATE>
   <CHANGE>-0.086</CHANGE>
 </CURRENCY>
</CURRENCIES>

I want to find specific currncy from the element "NAME" and "COUNTRY", and take the value "RATE".

I wrote:

public void ConvertCurrency(int value, string currency)
    {

        WebClient webClient = new WebClient();
        XDocument xml = new XDocument();
        webClient.DownloadFile("http://www.boi.org.il/currency.xml", @"currency.xml");
        XDocument currency_xml = XDocument.Load("currency.xml");

        var findCurrency = from currency1 in currency_xml.Descendants("CURRENCIES")
                           where (Convert.ToString(currency1.Element("CURRENCY").Element("NAME").Value) == currency) && (Convert.ToString(currency1.Element("CURRENCY").Element("COUNTRY").Value) == "USA")
                           select currency1.Element("RATE").Value;
        int rate = Convert.ToInt32(findCurrency);

        int result = value * rate;
        Console.WriteLine("Result:{0}",result);

    }

How can I do it right?

Upvotes: 1

Views: 159

Answers (2)

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101681

Jon Skeet's answer is complete, anyway here is your fixed query with LINQ syntax

var findCurrency = (from c in currency_xml.Descendants("CURRENCY")
                      where (string)c.Element("NAME") == currency
                           && (string)c.Element("COUNTRY") == "USA"
                             select (string)c.Element("RATE")).FirstOrDefault();

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500515

Your query is over CURRENCIES elements, and you're only looking at the first CURRENCY child. Then you're looking for a RATE child within CURRENCIES rather than CURRENCY. Additionally, you're getting a sequence of integers - and that isn't a single int. I think you want:

// Load directly from the web - it's simpler...
XDocument doc = XDocument.Load("http://www.boi.org.il/currency.xml");
var element = doc.Root
                 .Elements("CURRENCY")
                 .Where(x => (string) x.Element("COUNTRY") == "USA") &&
                             (string) x.Element("NAME") == currency)
                 .FirstOrDefault();
if (element != null)
{
    // You don't want an int here - you shouldn't lose information!
    decimal rate = (decimal) element.Element("RATE");
    decimal result = value * rate;
    Console.WriteLine("Result: {0}", result);
}
else
{
    Console.WriteLine("Couldn't find currency rate for USA");
}

Notes:

  • I haven't used a query expression here as it wouldn't help to simplify anything
  • This will fail if there's a CURRENCY element for USA without a RATE element; do you need to fix that?
  • I prefer to use the user-defined conversions in XElement instead of using Convert.ToXyz; they're specifically geared up for XML values (so won't use the culture when converting decimal values, for example)

Upvotes: 1

Related Questions