access xml element by attribute value

13,397

Solution 1

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);
    }
}

Solution 2

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']
Share:
13,397

Related videos on Youtube

Red Swan
Author by

Red Swan

Updated on June 04, 2022

Comments

  • Red Swan
    Red Swan almost 2 years

    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.

  • hoipolloi
    hoipolloi over 12 years
    What are the advantages of using LINQ? I haven't developed in C# since .NET 1.2. FYI, I've just bought your book to bring myself up to speed with 4. :)
  • Jon Skeet
    Jon Skeet over 12 years
    @hoipolloi: I find it helps to keep the data parts away from the code parts - the compiler can detect syntax errors at compile-time, you know that the methods (Descendants etc) will really be there - all that's deferred until execution time are the genuine data-dependent aspects. LINQ to XML also makes namespace handling a breeze :)
  • Red Swan
    Red Swan over 12 years
    @Jon Skeet: I already tried these expressions but i am getting "Expression cannot contain lambda expressions". If i am right then "Parent" must be the XDocument object loaded with xml document. why should i am getting this exception?
  • Red Swan
    Red Swan over 12 years
    It is working perfect. but is there any way to achieve this by LINQ or any entity framework object medel?
  • Jon Skeet
    Jon Skeet over 12 years
    @Red Swan: Please show a short but complete program demonstrating the problem. It should be fine.
  • Jon Skeet
    Jon Skeet over 12 years
    @Red Swan: Your code tries to cast to string? which is an invalid type - you can only use ? as a suffix for non-nullable value types.
  • Red Swan
    Red Swan over 12 years
    umm... i changed that and tried again. but still not accepting lambda expression.
  • Jon Skeet
    Jon Skeet over 12 years
    @Red Swan: It compiles perfectly for me. Do you have using System.Linq; in your using directives? Please post the exact error message in your question.
  • Red Swan
    Red Swan over 12 years
    Yes Jon Skeet, i have added my exception in question. in fact till, i am not using lambda expression, it works fine. but as soon i trying lambda expression it is showing me this exception.
  • Jon Skeet
    Jon Skeet over 12 years
    @Red Swan: I've added a short but complete program which compiles and runs without error. Are you trying to do something funky like running this as part of a LINQ to SQL query?
  • Red Swan
    Red Swan over 12 years
    @JonSkeet, I am getting this at execution time, in immediate window.
  • Jon Skeet
    Jon Skeet over 12 years
    @Red Swan: Then don't run it in the immediate window! Put it as part of a real program. It sounds like the immediate window doesn't support lambda expressions. In future please mention things like "I'm trying to run it in the immediate window" when you have problems - it changes things completely.
  • Red Swan
    Red Swan over 12 years
    @JonSkeet: Thanks John Skeet, its working in real code perfectly. i think i am habitual with immediate window :) i will strictly remember next time. Nice to brainstorming with you. Thanks champ.
  • Jon Skeet
    Jon Skeet over 12 years
    @Red Swan: Cool. Do you think the code in my edit is still useful, or shall I get rid of it?