Red Swan
Red Swan

Reputation: 15545

access xml element by attribute value

Probably this question repeated, but i am not satiesfied with existing answers. I want to get xml element from dynamically generated xml file by attribute value. we don't know how many nodes, and its herarchy. but each element, its sub element, its sub-sub elements, sub-sub-sub elements...so on will contain unique guid as "Id" attribute :

    <Element id="">
  <SubElement id=""></SubElement>
  <SubElement id="">
    <SubSubElement id="">
      <SubSubSubElement id="">
        <SubSubSubSubElement id="">....other sub inside this ...</SubSubSubSubElement>
      </SubSubSubElement>
    </SubSubElement>
  </SubElement>
</Element>

I want to find the element by only passing the Guid value. nonethless of its xpath, its node location / position. how can i do this in C#? is i need to use LINQ?

Edited:

 XDocument xmldoc = XDocument.Load(xmlFilePath);
XElement selectedElement = xmldoc.Descendants().Where(x => (string) x.Attribute("id") == myIdvalue).FirstOrDefault(); 

Exception : "Expression cannot contain lambda expressions" I have added Using System.Linq namspaces.

Upvotes: 10

Views: 17040

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1500635

hoipolloi has given an XPath answer, which is fine - but I would personally use LINQ to XML. (See my blog post on code and data for reasons.)

var element = parent.Descendants()
                    .Where(x => (Guid?) x.Attribute("id") == id)
                    .FirstOrDefault();

This will perform appropriate GUID parsing on each id attribute (returning a "null" Guid? value for non-GUIDs). If you're certain of the text format of your ID, you can cast to string instead:

var element = parent.Descendants()
                    .Where(x => (string) x.Attribute("id") == idText)
                    .FirstOrDefault();

Change the FirstOrDefault to Single, SingleOrDefault or First depending on your requirements.

EDIT: It's not at all clear what's going wrong with the code you've posted. Here's a short but complete program which shows it working fine. Please compare this with your code:

using System;
using System.Linq;
using System.Xml.Linq;

class Test
{
    static void Main()
    {
        string xml = "<parent><foo id='bar' /><foo id='baz' /></parent>";
        XDocument doc = XDocument.Parse(xml);
        string idToFind = "bar";
        XElement selectedElement = doc.Descendants()
            .Where(x => (string) x.Attribute("id") == idToFind).FirstOrDefault();
        Console.WriteLine(selectedElement);
    }
}

Upvotes: 12

hoipolloi
hoipolloi

Reputation: 8044

You can use XPath to do this. For instance, the following matches all elements with an id of 'foo', irrespective of their location in the document:

//*[@id='foo']

Upvotes: 5

Related Questions