如何用XElement LINQ筛选含指定两个子值的XML节点?
问题
给定如下XML结构:
<People> <Continent>Asia</Continent> <TimeZone>Hong Kong Standard Time</TimeZone> <Person> <FirstName>Joe</FirstName> <LastName>Stevenson</LastName> </Person> <Person> <FirstName>Joe</FirstName> <LastName>Hancock</LastName> </Person> <Person> <FirstName>Kirby</FirstName> <LastName>Stevenson</LastName> </Person> </People>
需要使用LINQ to XML筛选出同时包含"Joe"和"Stevenson"两个值的Person节点,且无需关注子元素的名称(例如能识别LastName为"Joe"、FirstName为"Stevenson"的错误数据)。
尝试了以下代码但未得到任何结果:
string trimmedFirstName = "Joe"; string trimmedLastName = "Stevenson"; List<XElement> peopleChildren = convertedPayload.Descendants("Person").Where(a => a.Value.Contains(trimmedFirstName) && a.Value.Contains(trimmedLastName)).ToList();
若将逻辑改为OR运算符,又会返回过多无关元素,求解决方案。
解决方案
问题出在XElement.Value会将当前节点下所有子元素的文本(包括XML中的换行、缩进空格)拼接成一个字符串,虽然理论上包含目标值,但这种方式不够精准,且容易受空白字符影响。
更可靠的方式是遍历Person节点的所有子元素,检查它们的文本(去除首尾空白后)是否同时包含两个目标值,不管子元素的名称和顺序:
string target1 = "Joe"; string target2 = "Stevenson"; List<XElement> matchingPeople = convertedPayload .Descendants("Person") .Where(person => { // 提取当前Person下所有子元素的文本并去除首尾空白 var childTextValues = person.Elements() .Select(element => element.Value.Trim()) .ToList(); // 检查是否同时包含两个目标值 return childTextValues.Contains(target1) && childTextValues.Contains(target2); }) .ToList();
说明
- 先提取
Person节点下所有子元素的文本并去除首尾空白,避免XML缩进、换行带来的干扰; - 直接检查这些文本集合中是否同时存在
"Joe"和"Stevenson",不管它们属于哪个子元素,完全符合需求; - 这种方式既不会遗漏符合条件的节点,也不会错误匹配只包含其中一个值的节点。
内容的提问来源于stack exchange,提问作者Kieran Ojakangas
相关产品推荐
相关产品推荐

