curiousDev
curiousDev

Reputation: 437

How to traverse through attributes in xml through LINQ

Please help me with the below mentioned scenario which has xml and i want the code in C# LINQ

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <Countries>
    <Country name="India">
      <state id="1"> Tamilnadu</state>
      <state> Karnataka</state>
    </Country>
    <Country name="America">
      <state id="1"> WI</state>
      <state> AW </state>
    </Country>
    <Country name="Africa">
      <state id="1"> Melbourne</state>
      <state> sydney </state>
    </Country>
  </Countries>
</root>

How to fetch state with attribute id=1 through LINQ since i am able to fetch attribute name="India"? And how to give id=1 i mean numeric value without "1"

Upvotes: 4

Views: 389

Answers (4)

gwiazdorrr
gwiazdorrr

Reputation: 6329

I find existing answers too verbose and lengthy. Imagine what would happen if you were going to do a selection based on multiple attributes?

The most compact and expressive at the same time solution is to use XPath extensions (from System.Xml.XPath namespace).

For instance, to get state with id=1 in India:

var xdoc = XDocument.Load(file);
foreach (var element in xdoc.XPathSelectElements("//Country[@name='India']/state[@id=1]"))
{
    Console.WriteLine("State " + element.Value + ", id " + (int)element.Attribute("id"));
}

To get all states in all countries that have any id assigned:

foreach (var element in xdoc.XPathSelectElements("//state[@id]"))
{
    Console.WriteLine("State " + element.Value + ", id " + (int)element.Attribute("id"));
}

Etc.

You can find XPath specification here.

Upvotes: 0

Darren
Darren

Reputation: 70728

If you are using C# you could do something like:

 XDocument document = XDocument.Load("filePath");

 var states = (from state in document.Root.Descendants("state")
               where state.Attribute("id") != null && state.Attribute("id").Value == "1" 
               select state).ToList();

Upvotes: 2

Chuck Savage
Chuck Savage

Reputation: 11955

Try the following.

XDocument xml = XDocument.Load(file);

XElement state = xml.Root.Descendants("Country")
    .First(c => c.Attribute("name").Value == "India")
    .Descendants("state")
    .First(s => (int)s.Attribute("id") == 1);

Next time post what you have tried first, so we can help you with your code.

Also I did this without null checks. If the values aren't found it will die on First(). Up to you to do your own safety checks.

Upvotes: 2

Mathew Thompson
Mathew Thompson

Reputation: 56429

You could do the following:

The null check is important, as judging by your structure without that null check you'll get a NullReferenceException.

XDocument xml = XDocument.Load("yourFileLocation");

var items = document.Root.Descendants("state")
    .Where(s => s.Attribute("id") != null && s.Attribute("id").Value == "1")
    .ToList();

Upvotes: 2

Related Questions