如何使用 LINQ to XML 获取属性值?

Posted

技术标签:

【中文标题】如何使用 LINQ to XML 获取属性值?【英文标题】:How to get attribute value using LINQ to XML? 【发布时间】:2013-01-10 11:38:03 【问题描述】:
<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();

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

但我需要WorkPhone 列的值424-555-0545 而不是HomeHomePhone 列的值423-555-0124 而不是Home

我应该怎么做?

【问题讨论】:

【参考方案1】:

使用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,
                ;

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

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

如果没有“电话”元素满足条件,SingleOrDefault 将等于 null,并且XElement 上的string 转换等效于XElement.Value

【讨论】:

或者在 C# 6+ 中,您可以使用 Null-conditional operator,而不是强制转换以避免 NullReferenceException。所以它看起来像:Name = emp.Element("Name")?.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")                               
    ;

stringint 等使用转换元素,而不是访问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>

【讨论】:

以上是关于如何使用 LINQ to XML 获取属性值?的主要内容,如果未能解决你的问题,请参考以下文章

在值中搜索字符串并在 VB.NET 中的 LINQ to XML 中获取属性值

Linq to XML - 使用命名空间获取元素

使用 LINQ 从 XML 获取三个输入中的最大属性值

C# Linq to XML 读取多个带有属性的标签

如何使用 linq-to-xml 查询简化此功能?

在带有 LINQ to XML 的 VB.NET 中,where 子句在属性值和字符串之间设置不区分大小写的比较