web-dev-qa-db-ja.com

LINQ to XMLを使用して属性値を取得するにはどうすればよいですか?

<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

しかし、WorkPhoneの代わりに列Homeの値424-555-0545が必要であり、HomePhoneの代わりに列Homeの値423-555-0124が必要です。

そのために私は何をすべきですか?

13
Chandru A

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")は、empのすべての「電話」要素で列挙可能です。
  • Singleは、指定されたプロパティを満たす要素を取得します(プロパティを満たす要素が0個または複数ある場合、エラーが発生します)。
  • phoneElement.Attribute("Type").Valueは、属性「Type」(つまり「Home」または「Work」)の値です。

次に、コードは次のようになります。

_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,
                };
_

要素empWork phoneまたはHome phone numberがない場合、上記のコードはSingleで例外を発生させます。このケースに対処するには、コードを次のように変更する必要があります。

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

SingleOrDefaultは、条件を満たす「Phone」要素がなく、nullにキャストされたstringが_XElement.Value_と同等である場合、XElementと等しくなります。

15
Cédric Bignon

このコードは、従業員に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プロパティにアクセスする代わりに、キャスト要素をintValueなどに使用します。どうして? 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>
3