1

In this question I found out how to use

XDocument MyData = XDocument.Load(FILENAME);
string color = MyData.Descendants("Red").Elements("Shade")
                     .Where(y => (int)y.Attribute("id") == 3).FirstOrDefault().Value;

to get an element by specifying an attribute "id". The above returns "lava" from the Xml below.

 <colours>
<Red>
<Shade id="1">
 <colour>crimson</colour>
 </Shade>
<Shade id="2">
 <colour>raspberry</colour>
 </Shade>
<Shade id="3">
 <colour>lava</colour>
 </Shade>
<Shade id="4">
 <colour>scarlet</colour>
 </Shade>
 </Red>
<Green>
<Shade id="1">
 <colour>asparagus</colour>
 </Shade>
<Shade id="2">
 <colour>emerald</colour>
 </Shade>
<Shade id="3">
 <colour>lime</colour>
 </Shade>
<Shade id="4">
 <colour>avocado</colour>
 </Shade>
 </Green>
<Blue>
<Shade id="1">
 <colour>cyan</colour>
 </Shade>
<Shade id="2">
 <colour>sapphire</colour>
 </Shade>
<Shade id="3">
 <colour>powder</colour>
 </Shade>
<Shade id="4">
 <colour>iris</colour>
 </Shade>
 </Blue>
 </colours>

In the following example my Shade elements have an extra attribute called 'group' (I've only added them to 'Red' for the sake of keeping it short. I need to do something similar to the previous, only this time instead of searching on an 'id' and returning its 'colour', I want to search on an 'id' and return its 'group' value.

One solution would be to change 'group' from an attribute to an element, which make adapting the Linq to Xml above more straightforward but I'm eager to see what a solution for the existing Xml would look like.

I'm also eager to learn more about Linq to Xml and using Lambda expressions like this. Any good learning resources you can point me towards will be very gratefully received.

 <colours>
<Red>
<Shade id="1" group="yes">
 <colour>crimson</colour>
 </Shade>
<Shade id="2" group="no">
 <colour>raspberry</colour>
 </Shade>
<Shade id="3" group="yes">
 <colour>lava</colour>
 </Shade>
<Shade id="4" group="no">
 <colour>scarlet</colour>
 </Shade>
 </Red>
<Green>
<Shade id="1">
 <colour>asparagus</colour>
 </Shade>
<Shade id="2">
 <colour>emerald</colour>
 </Shade>
<Shade id="3">
 <colour>lime</colour>
 </Shade>
<Shade id="4">
 <colour>avocado</colour>
 </Shade>
 </Green>
<Blue>
<Shade id="1">
 <colour>cyan</colour>
 </Shade>
<Shade id="2">
 <colour>sapphire</colour>
 </Shade>
<Shade id="3">
 <colour>powder</colour>
 </Shade>
<Shade id="4">
 <colour>iris</colour>
 </Shade>
 </Blue>
 </colours>
Community
  • 1
  • 1

2 Answers2

2

Since group is an attribute, you can use .Attribute method like this:-

var colors = MyData.Root.Element("Red")
                        .Elements("Shade")
                        .FirstOrDefault(y => (int)y.Attribute("id") == 3);
string group;
if (colors != null)
        group = (string)colors.Attribute("group");

Description:

We need to start from root node so MyData.Root will give colours which is the root node, then we need to pick the Red element because we don't have multiple Red node so it makes no sense to use Descendants here. Now inside Red node we can use Elements method to fetch all Shade nodes. (Why we are not using Descendants here? Check difference between them.) Finally we are using FirstOrDefault method to fetch the first node having id attribute as 3. It will return null if no node satisfies the condition, this is the reason we are first checking if it is returning null only then fetching the group attribute otherwise it will throw Null reference exception.

Community
  • 1
  • 1
Rahul Singh
  • 21,585
  • 6
  • 41
  • 56
1

try

string color = MyData.Descendants("Red").Elements("Shade").Where(y => (int)y.Attribute("id") == 3).FirstOrDefault().Attribute("group");
Oxoron
  • 664
  • 1
  • 7
  • 26
  • using var color = ... etc then referring to color.Value worked! Lovely, thank you. – Paul Rathbone Oct 23 '15 at 10:07
  • @PaulRathbone - If the answer helped you, you should thank by upvoting \ accepting the answer. This is how this community works. Check this - http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – Rahul Singh Oct 23 '15 at 15:37
  • 1
    Thanks for the heads-up Rahul. Until this moment I had less than 15 experience points so I was unable to upvote. – Paul Rathbone Oct 24 '15 at 05:11