0

Given the below xml I need to return all the employees that belong to a department. So when DepartmentName=Fashion should return 3 employees

    <?xml version="1.0" encoding="utf-8" ?>
    <Store>
      <Departments>
        <Department name="Fashion">
          <Employees>
            <Employee FirstName="Jo" Surname="Blogg"/>
            <Employee FirstName="Mark" Surname="Smith"/>
            <Employee FirstName="Rose" Surname="Blogg2"/>
          </Employees>
        </Department>    
        <Department name="Makeup">
          <Employees>     
            <Employee FirstName="Sonia" Surname="Smith2"/>
            <Employee FirstName="Jenny" Surname="Blogg3"/>
          </Employees>
        </Department>   
     </Departments>   
    </Store>

what I have tried but does not compile and other tries didnt return the wanted result

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml.Linq;

    namespace ConsoleApplicationXml
    {
        class Program
        {
            static void Main(string[] args)
            {
                var xDocument = XDocument.Load("Store.xml");

                //Get all employees that belong to "Fashion
                string departmentName = "Fashion";

       //compiles but get object variable not set
        var employees = (from emp in xDocument.Descendants("Employees")
                         where (emp.Parent.FirstAttribute.Value == departmentName)

                         select new Employee
                         {
                             DepartmentName = departmentName,
                             FirstName = emp.FirstAttribute.Value,
                             Surname = emp.LastAttribute.Value
                         }).ToList();

//DOES NOT COMPILE!!

                var employees = (from emp in xDocument.Descendants("Employees")
                                 where (emp.Parent.FirstAttribute.Value == departmentName)
                                 let xFirstName = emp.Element("Employee").FirstAttribute("FirstName")
                                 let xLastName = emp.Element("LastName")
                    select new Employee
                    {
                        DepartmentName = departmentName,
                        FirstName = xFirstName.Value,
                        Surname = xLastName.Value
                    }).ToList();
            }
        }

        public class Employee
        {
            public string DepartmentName { get; set; }
            public string FirstName { get; set; }
            public string Surname { get; set; }
        }
    }
developer9969
  • 4,628
  • 6
  • 40
  • 88

2 Answers2

0

You can use two from clause a.k.a SelectMany() to filter Department elements and select corresponding Employee elements :

var employees = (from department in xDocument.Descendants("Department")
                 from emp in department.Descendants("Employee")
                 where department.Attribute("name").Value == departmentName
                 select new Employee
                 {
                    DepartmentName = departmentName,
                    FirstName = emp.Attribute("FirstName").Value,
                    Surname = emp.Attribute("Surname").Value
                 }).ToList();
har07
  • 88,338
  • 12
  • 84
  • 137
  • Hi thanks that defenitely works. are you saying you can also do with select many direct and eliminate the 2 from clauses? – developer9969 May 21 '16 at 13:18
  • Yes, `SelectMany()` is the equivalent method for the 2 `from` clauses in query style : http://stackoverflow.com/questions/6414816/is-there-a-c-sharp-linq-syntax-for-the-queryable-selectmany-method – har07 May 21 '16 at 13:27
0

In your first example

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace ConsoleApplicationXml
{
    class Program
    {
        static void Main(string[] args)
        {
            var xDocument = XDocument.Load("Store.xml");

            //Get all employees that belong to "Fashion
            string departmentName = "Fashion";

   //compiles but get object variable not set
    var employees = (from emp in xDocument.Descendants("Employees")
                     where (emp.Parent.FirstAttribute.Value == departmentName)

                     select new Employee
                     {
                         DepartmentName = departmentName,
                         FirstName = emp.FirstAttribute.Value,
                         Surname = emp.LastAttribute.Value
                     }).ToList();

what you are doing wrong is that the emp variable is for the Employees tag, therefore the FirstAttribute and LastAttribute you are trying to use have no meaning. Use instead this code:

var employeesParent = xDocument.Descendants("Employees").Where(element => element.Parent.Attribute("name").Value == departmentName);
var employees = (from emp in employeesParent.Descendants()
                         select new Employee
                         {
                             DepartmentName = departmentName,
                             FirstName = emp.Attribute("FirstName").Value,
                             Surname = emp.Attribute("Surname").Value
                         }).ToList();

I hope it helps.

  • thanks that works too.You answer does help me to understand where i was going wrong.thank you. I did already accept the other answer that came before yours. – developer9969 May 21 '16 at 13:51