C# Query XML with Linq to find match

Here is a snippet of my XML (with only a few entries whereas there are actually around a thousand).

<?xml version="1.0" encoding="UTF-8"?>
<information_code version="3.5">
  <entry code="000" title="Function, data for plans and description"/>
  <entry code="001" title="Title page"/>
  <entry code="002" title="List of pages or data modules"/>
  <entry code="003" title="Change records and highlights"/>
  <entry code="004" title="Access illustration"/>
</information_code>

What I need to do is match the 'code' attribute with a value that I pass into my query, then return the value of the 'title' attribute. It really shouldn't be hard but I'm going around in circles.

Here's where I currently am, but it always gets caught without matching. Obviously something wrong with my query.

private string getInfoName(string infoCode)
{
    XDocument mydoc = XDocument.Load(GlobalVars.pathToInfoCodes);
    string name = string.Empty;

    try
    {
        var entry = mydoc
            .Elements("entry")
            .Where(e => e.Attribute("code").Value == infoCode)
            .Single();

        name = entry.Attribute("title").Value;
    }
    catch
    {
        MessageBox.Show("Info code not recognised: " + infoCode);
    }        
   return name;
}

Upvotes: 1

Views: 498

Answers (1)

Gilad Green
Gilad Green

Reputation: 37299

The problem is that when you use Elements it searches only in the level you are currently at, which in this point is the <information_code> - so there are no <entry> elements there.

You can use .Element("information_code").Elements("entry") or use instead .Descendants:

string wantedCode = "001";

var title = XDocument.Load(GlobalVars.pathToInfoCodes)
         .Descendants("entry")
         .Where(e => e.Attribute("code")?.Value == wantedCode)
         .Select(e => e.Attribute("title").Value).FirstOrDefault();

You can also do it with the query syntax. Might look nicer:

var title = (from e in XDocument.Load("data.xml").Descendants("entry")
             where e.Attribute("code")?.Value == wantedCode
             select e.Attribute("title")?.Value).FirstOrDefault();

Note that the ?. syntax is C# 6.0 Null Propagation. If you are with an earlier C# version then you will have to store the attribute in a variable, check that it is not null and only then access .Value

Upvotes: 1

Related Questions