如何用LINQ从复杂XML中筛选含Individual的sdnEntry元素?
问题:获取XML中
sdnType为Individual的sdnEntry元素 我有一个带命名空间的XML,需要提取所有<sdnType>值为Individual的<sdnEntry>元素,但尝试的代码无法正常运行。
我的XML内容
string list = @"<?xml version='1.0' standalone='yes'?> <sdnList xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://tempuri.org/sdnList.xsd'> <sdnEntry> <uid>36</uid> <lastName>AEROCARIBBEAN</lastName> <sdnType>Entity</sdnType> <programList> <program>CUBA</program> </programList> </sdnEntry> <sdnEntry> <uid>173</uid> <lastName>ANGLO-CARIBBEAN</lastName> <sdnType>Entity</sdnType> <programList> <program>CUBA</program> </programList> </sdnEntry> <sdnEntry> <uid>2681</uid>> <title>NAME1 SURNNAME1</title> <sdnType>Individual</sdnType> <programList> <program>SDGT</program> </programList> </sdnEntry> <sdnEntry> <uid>2682</uid> <title>NAME2 SURNNAME2</title> <sdnType>Individual</sdnType> <programList> <program>SDGT</program> </programList> <idList> <id> <uid>1002</uid> <idType>Passport</idType> <idNumber>304555</idNumber> <idCountry>Egypt</idCountry> </id> </idList> </sdnEntry> </sdnList>";
尝试的错误代码
listXML.LoadXml(list); XDocument sndList = XDocument.Parse(listXML.OuterXml); var nls = XNamespace.Get("http://tempuri.org/sdnList.xsd"); //TEST 1 var individ = sndList.Elements(nls + "sdnEntry") .SelectMany(r => r.Descendants("sdnType").Where(e => (string)e.Element("sdnType").Value == "Individual")); //TEST 2 IEnumerable<XElement> individuals = from element in sndList.Root.Elements(nls + "sdnEntry") where (string)element.Element("sdnType") == "Individual" select element;
错误原因分析
- 命名空间未全局应用:XML根节点声明了默认命名空间
xmlns='http://tempuri.org/sdnList.xsd',所有子元素(包括sdnType)都属于该命名空间。代码中获取sdnType时未加命名空间前缀,导致无法匹配元素,element.Element("sdnType")返回null。 - TEST1逻辑错误:
SelectMany用法有误,试图在sdnType元素下查找sdnType子元素(e.Element("sdnType")),这不符合XML结构;且该逻辑返回的是sdnType元素,而非目标sdnEntry元素。 - 冗余XML转换:先加载到
XmlDocument再转XDocument完全多余,直接用XDocument.Parse(list)即可完成加载。
正确解决方案
方法1:LINQ查询语法
XDocument sndList = XDocument.Parse(list); XNamespace nls = XNamespace.Get("http://tempuri.org/sdnList.xsd"); IEnumerable<XElement> individuals = from entry in sndList.Root.Elements(nls + "sdnEntry") let sdnType = entry.Element(nls + "sdnType") where sdnType != null && sdnType.Value == "Individual" select entry;
方法2:方法链语法
XDocument sndList = XDocument.Parse(list); XNamespace nls = XNamespace.Get("http://tempuri.org/sdnList.xsd"); var individuals = sndList.Root .Elements(nls + "sdnEntry") .Where(entry => { var sdnType = entry.Element(nls + "sdnType"); return sdnType != null && sdnType.Value == "Individual"; });
关键说明
- 所有元素访问必须携带命名空间
nls,包括sdnType。 - 添加
sdnType != null判断,可避免XML中缺失sdnType元素时触发空引用异常。 - 直接通过
XDocument.Parse(list)加载XML,简化流程。
内容的提问来源于stack exchange,提问作者Emerson Rios
相关产品推荐
相关产品推荐

