viky
viky

Reputation: 17669

Conditional Output by Linq to XML

Below is the sample XML that I am trying to read using Linq to XML:

<root>
  <Employee>
    <Name>Jeff</Name>
    <Department>Account</Department>
  </Employee>
  <Employee>
    <Name>David</Name>
    <Department>Finance</Department>
  </Employee>
  <Employee>
    <Name>Neil</Name>
    <Department>Sales</Department>
  </Employee>
  <Employee>
    <Name>Jason</Name>
    <Department>Retail</Department>
  </Employee>
</root>

Now, I need to select Employee elements which are from "Account" Department. If there are none in Account then I need to pick Employee element from Finance. How can I do that?

Upvotes: 4

Views: 176

Answers (3)

Gilad Green
Gilad Green

Reputation: 37299

Combining Linq and XPath you can do it like this:

var document = XDocument.Load("data.xml").Root;
//Find a Department with a given value and retrieve its Employee parent
string xPath = "//Department[text() = '{0}']/parent::Employee";

//Search for "Account" Department. If nun was found will return null and then
//search for "Finance"
var employee = document.XPathSelectElement(string.Format(xPath, "Account")) ??
               document.XPathSelectElement(string.Format(xPath, "Finance"));

If you do not want to use XPath then you can do this:

var employee = (from item in XDocument.Load("data.xml").Descendants("Employee")
                let department = item.Element("Department").Value
                orderby department == "Account" ? 1 :
                        department == "Finance" ? 2 : 3
                select item).FirstOrDefault();

For all employees of those departments:

var employee = (from item in XDocument.Load("data.xml").Descendants("Employee")
                group item by item.Element("Department").Value into grouping
                orderby grouping.Key == "Account" ? 1 :
                        grouping.Key == "Finance" ? 2 : 3
                select grouping.ToList()).FirstOrDefault();

Upvotes: 0

Reza Aghaei
Reza Aghaei

Reputation: 125197

As an option you can use this code:

var result = XElement.Parse(xml).Descendants("Employee")
                     .GroupBy(x => x.Element("Department").Value)
                     .OrderByDescending(x=>x.Key=="Account")
                     .FirstOrDefault(x => (x.Key == "Account" && x.Count() > 0) ||
                                           x.Key == "Finance").ToList();

Upvotes: 1

mybirthname
mybirthname

Reputation: 18127

You can do this, it is not the most elegant way. Just use || and take FirstOrDefault

 var result = doc.Root.Descendants("Employee").
               Where(x => x.Element("Department").Value == "Account" || x.Element("Department").Value == "Finance").
               FirstOrDefault();

Upvotes: 0

Related Questions