调用XContainer.Element返回null,XML属性获取失败问题排查
问题:获取XML属性时出现System.Xml.Linq.XContainer.Element(...) returned null错误
我编写了postXMLData方法用于发送POST请求并获取XML格式的响应。在接收到响应后,我尝试获取名称以“f”开头的属性,却遇到错误System.Xml.Linq.XContainer.Element(...) returned null。请问我哪里出错了?
postXMLData方法代码
public static XmlDocument postXMLData(string xml) { var request = (HttpWebRequest)WebRequest.Create(Requests.url); byte[] bytes; bytes = System.Text.Encoding.ASCII.GetBytes(xml); request.ContentType = "text/xml; encoding='utf-8'"; request.ContentLength = bytes.Length; request.Method = "POST"; Stream requestStream = request.GetRequestStream(); requestStream.Write(bytes, 0, bytes.Length); requestStream.Close(); HttpWebResponse response; response = (HttpWebResponse)request.GetResponse(); if (response.StatusCode == HttpStatusCode.OK) { using (var streamReader = new StreamReader(response.GetResponseStream())) { var responseText = streamReader.ReadToEnd(); var result = new XmlDocument(); result.LoadXml(responseText); return result; } } throw new Exception(); }
请求返回的响应XML
<response result="0"> <prov> <getStatus result="0"> <pay date="2023-02-08T19:44:33+03:00" fatal="false" id="8022140013003" result="0" status="2" uid="26775263057008" value-date="2023-02-08T19:44:40+03:00"> </pay> </getStatus> </prov> </response>
获取属性的代码
XmlDocument doc = postXMLData(Requests.getStatus("08022140013003")); XElement e = XElement.Load(new XmlNodeReader(doc)); Console.WriteLine(e); //此处正常输出 IEnumerable<XAttribute> attrs1 = e.Element("response").Element("prov").Element("getStatus").Element("pay")?.Attributes().Where(a => a.Name.LocalName.StartsWith("f")); Console.WriteLine(attrs1); Console.ReadKey();
错误原因及修正方案
核心错误
你加载后的XElement e本身就是XML的根节点<response>,此时调用e.Element("response")会尝试找根节点下名为response的子元素,而根节点的子元素是<prov>,所以这一步直接返回null,后续链式调用自然报错。
修正后的获取属性代码
// 直接从根节点e开始查找子元素prov IEnumerable<XAttribute> attrs1 = e.Element("prov") .Element("getStatus") .Element("pay") ?.Attributes() .Where(a => a.Name.LocalName.StartsWith("f"));
额外优化建议
避免XmlDocument与XElement混用
可以直接在postXMLData方法中返回XElement,省去类型转换步骤,同时优化资源释放:public static XElement postXMLData(string xml) { var request = (HttpWebRequest)WebRequest.Create(Requests.url); // 用UTF8编码,和请求头的utf-8保持一致,避免乱码 byte[] bytes = System.Text.Encoding.UTF8.GetBytes(xml); request.ContentType = "text/xml; encoding=utf-8"; request.ContentLength = bytes.Length; request.Method = "POST"; // 使用using自动释放流资源 using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(bytes, 0, bytes.Length); } using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { if (response.StatusCode == HttpStatusCode.OK) { using (var streamReader = new StreamReader(response.GetResponseStream())) { var responseText = streamReader.ReadToEnd(); return XElement.Parse(responseText); } } throw new Exception("请求未返回成功状态"); } }调用时简化为:
XElement e = postXMLData(Requests.getStatus("08022140013003")); IEnumerable<XAttribute> attrs1 = e.Element("prov") .Element("getStatus") .Element("pay") ?.Attributes() .Where(a => a.Name.LocalName.StartsWith("f"));编码统一
原代码中用Encoding.ASCII处理XML字节,可能导致非ASCII字符乱码,建议替换为Encoding.UTF8,与请求头中声明的utf-8编码匹配。
内容的提问来源于stack exchange,提问作者John Paul Johns
相关产品推荐
相关产品推荐

