Find a node by attribute and return a different attribute's value from that same node

1.4k Views Asked by At

I have for example the following data in an xml file:

<Critic-List>
  <bruce-bennett>
   <Movie Title="White House Down (2013)" Score="C+" Like="false"/>
   <Movie Title="Despicable Me 2 (2013)" Score="A-" Like="true"/>
   <Movie Title="World War Z (2013)" Score="B+" Like="true"/>
   <Movie Title="Man of Steel (2013)" Score="B+" Like="true"/>

how do i write a code which

  1. selects a node by attribute- say attribute(title)="Despicable Me 2 (2013)"
  2. and from that selected node gives the value for another attribute of that node- for instance: attribute(like)... (which in this case would return "true")

XML readers in C# seems more geared towards returning "inner text" rather than attribute values, I'm wondering if maybe I should have stored my xml data in inner text rather than attributes.. to me it would be much more convenient to retrieve the data values of attributes, but i'm not sure if those parameters exist...

any help or suggested reading would be much appreciated!

4

There are 4 best solutions below

0
On BEST ANSWER

I'm not sure what method your trying to use to get the result, LINQ to XML is definitely a good way to do so. If you're trying to use XPath, here is how you would achieve the same outcome.

var xml = @"<Critic-List>
  <bruce-bennett>
   <Movie Title=""White House Down (2013)"" Score=""C+"" Like=""false""/>
   <Movie Title=""Despicable Me 2 (2013)"" Score=""A-"" Like=""true""/>
   <Movie Title=""World War Z (2013)"" Score=""B+"" Like=""true""/>
   <Movie Title=""Man of Steel (2013)"" Score=""B+"" Like=""true""/>    
  </bruce-bennett>
  </Critic-List>";
XElement doc = XElement.Parse(xml);

var node = doc.XPathSelectElement("//Movie[@Title='Despicable Me 2 (2013)']");
var like = node.Attribute("Like").Value;

The w3schools is a good site to get some tutorials on XPath. Options are always a good way to expand your horizons.

0
On

I simplified the your XML a bit, but the idea is the same. As a first step you build a list of attributes that satisfy your criteria and then you pick up the first discovered element.

   const string myXml = @"<Critic-List>
                                   <Movie Title='White House Down (2013)' Score='C+' />
                                   <Movie Title='Despicable Me 2 (2013)' Score='A-' />
                                   <Movie Title='World War Z (2013)' Score='B+' />
                                   <Movie Title='Man of Steel (2013)' Score='B+' />
                         </Critic-List>";

   var el = XElement.Parse(myXml);
   var q1 = el.Elements()
                 .Select(n => (n.Attribute("Title").Value == "Despicable Me 2 (2013)") ? n.Attribute("Score") : null)
                 .First(n => n != null);
0
On

You can use LINQ to XML like this:

XElement doc = XElement.Load("File.xml");
var node = (from e in doc.Elements()
    where (string)e.Attribute("Title") == "Despicable Me 2 (2013)"
    select e).SingleOrDefault;

var like = (bool)node.Attribute("Like");
0
On

This is a pretty clean way.

XElement ele = XElement.Parse(movieXml);
string movie = "Despicable Me 2 (2013)";
string answer = ele.Descendants("Movie")
                   .Where(x => x.Attribute("Title").Value == movie)
                   .Select(x => x.Attribute("Like").Value)
                   .FirstOrDefault();