2013-01-26 2 views
9
<Employees> 
    <Employee> 
    <EmpId>1</EmpId> 
    <Name>Sam</Name> 
    <Sex>Male</Sex> 
    <Phone Type="Home">423-555-0124</Phone> 
    <Phone Type="Work">424-555-0545</Phone> 
    </Employee> 
</Employees> 

private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 

     emplyeeDetails = XDocument.Load(Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName + "\\LinqToXml\\Xmls\\" + "Employees.xml"); 
     var emplyees = from emp in emplyeeDetails.Descendants("Employee").Take(10) 
         orderby emp.Element("EmpId").Value ascending 
         select new 
         { 
          Id = emp.Element("EmpId").Value, 
          Name = emp.Element("Name").Value, 
          Sex = emp.Element("Sex").Value, 
          WorkPhone=emp.Element("Phone").Attribute("Type").Value, 
          HomePhone = emp.Element("Phone").Attribute("Type").Value,        

         }; 
     DgrdEmployeeDetails.ItemsSource = emplyees.ToList(); 
    } 

Используя приведенный выше код, я могу получить результат ниже. enter image description hereКак получить значение атрибута с помощью linq для xml?

Но я нужен столбец (WorkPhone) значение 424-555-0545 вместо Главной и колонок (HomePhone) значения 423-555-0124 вместо Главной , Что я должен сделать для этого?

ответ

11

Используйте Where метод:

Для домашнего телефона телефон:

emp.Elements("Phone").Single(phoneElement => phoneElement.Attribute("Type").Value == "Home").Value 

Для номер рабочего телефона:

emp.Elements("Phone").Single(phoneElement => phoneElement.Attribute("Type").Value == "Work").Value 
  • emp.Elements("Phone") является enumer способный ко всем элементам «Телефон» emp.
  • Single получит элемент, который удовлетворяет указанному свойству (если есть 0 или более одного элемента, которые удовлетворяют этому свойству, возникает ошибка).
  • phoneElement.Attribute("Type").Value является значением атрибута «Тип» (т.е. «Home» или «Работа»)

Тогда ваш код должен быть:

var emplyees = from emp in emplyeeDetails.Descendants("Employee").Take(10) 
       orderby emp.Element("EmpId").Value ascending 
       select new 
       { 
        Id = emp.Element("EmpId").Value, 
        Name = emp.Element("Name").Value, 
        Sex = emp.Element("Sex").Value, 
        WorkPhone = emp.Elements("Phone").Single(phoneElement => phoneElement.Attribute("Type").Value == "Home").Value, 
        HomePhone = emp.Elements("Phone").Single(phoneElement => phoneElement.Attribute("Type").Value == "Work").Value, 
       }; 

Если элемент emp может не иметь Работа телефон или Номер телефона, приведенный выше код повысит исключение в Single. Чтобы справиться с этим делом вы должны изменить свой код:

(string)emp.Elements("Phone").SingleOrDefault(phoneElement => phoneElement.Attribute("Type").Value == "Home") 

SingleOrDefault будет равен null, если ни один элемент «Телефон» не удовлетворяет условию и string бросок на XElement эквивалентно XElement.Value.

2

Этот код будет работать, даже если есть какие-либо существуют Phone элементы для сотрудника:

var emplyees = 
    from emp in emplyeeDetails.Descendants("Employee").Take(10) 
    let phones = emp.Descendants("Phone") 
    orderby (int)emp.Element("EmpId") 
    select new 
    { 
     Id = (int)emp.Element("EmpId"), 
     Name = (string)emp.Element("Name"), 
     Sex = (string)emp.Element("Sex"), 
     WorkPhone = (string)phones.FirstOrDefault(p => (string)p.Attribute("Type") == "Work"), 
     HomePhone = (string)phones.FirstOrDefault(p => (string)p.Attribute("Type") == "Home")        
    }; 

Использование литья элементы string, int и т.д. вместо доступа к Value собственности. Зачем? Потому что, если в вашем xml есть какой-то недостающий элемент или атрибут, вы получите NullReferenceException. Но вместо этого кастинг вернет значение по умолчанию. Таким образом, код выше будет анализировать даже xml следующим образом:

<Employees> 
    <Employee> 
    <EmpId>1</EmpId> 
    <Name>Sam</Name> 
    <Phone Type="Home">423-555-0124</Phone> 
    <Phone>524-777-1234</Phone> 
    </Employee> 
</Employees> 
Смежные вопросы