如何使用 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
而不是Home
和HomePhone
列的值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")
;
对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>
【讨论】:
以上是关于如何使用 LINQ to XML 获取属性值?的主要内容,如果未能解决你的问题,请参考以下文章