如何使用linq到xml获取属性值?

时间:2022-11-26 23:01:25
<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();
    }

Using above code i can get the result below. 如何使用linq到xml获取属性值?

使用上面的代码我可以得到下面的结果。

But i need the column(WorkPhone) value 424-555-0545 instead of Home and the column(HomePhone) value 423-555-0124 instead of Home. What should i do for that ?

但我需要列(WorkPhone)值424-555-0545而不是Home和列(HomePhone)值423-555-0124而不是Home。我该怎么办?

2 个解决方案

#1


12  

Use the Where method:

使用Where方法:

For the Home phone number:

对于家庭电话号码:

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

For the Work phone number:

对于工作电话号码:

emp.Elements("Phone").Single(phoneElement => phoneElement.Attribute("Type").Value == "Work").Value
  • emp.Elements("Phone") is a enumerable on all "Phone" elements of emp.
  • emp.Elements(“Phone”)是emp的所有“Phone”元素的可枚举。
  • Single will get the element that satisfy the specified property (if there are 0 or more than 1 element that satisfy the property, an error is raised).
  • Single将获取满足指定属性的元素(如果有0个或多个元素满足该属性,则会引发错误)。
  • phoneElement.Attribute("Type").Value is the value of the attribute "Type" (ie "Home" or "Work")
  • phoneElement.Attribute(“Type”)。Value是属性“Type”的值(即“Home”或“Work”)

Then, your code should be:

然后,您的代码应该是:

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

If the element emp may have no Work phone or Home phone number, the above code will raise an exception in the Single. To deal with this case you have to change your code to:

如果元素emp可能没有Work电话号码或Home电话号码,则上述代码将在Single中引发异常。要处理这种情况,您必须将代码更改为:

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

SingleOrDefault will equal null if no "Phone" element satisfy the condition and the string cast on a XElement is equivalent to XElement.Value.

如果没有“Phone”元素满足条件并且在XElement上强制转换的字符串等效于XElement.Value,则SingleOrDefault将等于null。

#2


2  

This code will work even if there is any Phone elements exist for employee:

即使员工存在任何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")                               
    };

Use casting elements to string, int, etc instead of accessing Value property. Why? Because if there is some missing element or attribute in your xml, then you will get a NullReferenceException. But casting will return default value instead. So, code above will parse even xml like this:

将转换元素用于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>

#1


12  

Use the Where method:

使用Where方法:

For the Home phone number:

对于家庭电话号码:

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

For the Work phone number:

对于工作电话号码:

emp.Elements("Phone").Single(phoneElement => phoneElement.Attribute("Type").Value == "Work").Value
  • emp.Elements("Phone") is a enumerable on all "Phone" elements of emp.
  • emp.Elements(“Phone”)是emp的所有“Phone”元素的可枚举。
  • Single will get the element that satisfy the specified property (if there are 0 or more than 1 element that satisfy the property, an error is raised).
  • Single将获取满足指定属性的元素(如果有0个或多个元素满足该属性,则会引发错误)。
  • phoneElement.Attribute("Type").Value is the value of the attribute "Type" (ie "Home" or "Work")
  • phoneElement.Attribute(“Type”)。Value是属性“Type”的值(即“Home”或“Work”)

Then, your code should be:

然后,您的代码应该是:

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

If the element emp may have no Work phone or Home phone number, the above code will raise an exception in the Single. To deal with this case you have to change your code to:

如果元素emp可能没有Work电话号码或Home电话号码,则上述代码将在Single中引发异常。要处理这种情况,您必须将代码更改为:

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

SingleOrDefault will equal null if no "Phone" element satisfy the condition and the string cast on a XElement is equivalent to XElement.Value.

如果没有“Phone”元素满足条件并且在XElement上强制转换的字符串等效于XElement.Value,则SingleOrDefault将等于null。

#2


2  

This code will work even if there is any Phone elements exist for employee:

即使员工存在任何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")                               
    };

Use casting elements to string, int, etc instead of accessing Value property. Why? Because if there is some missing element or attribute in your xml, then you will get a NullReferenceException. But casting will return default value instead. So, code above will parse even xml like this:

将转换元素用于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>