C#解析API返回XML遇null节点如何避免空引用异常显示错误提示
问题场景
正在开发调用物流查询API的桌面程序,核心逻辑为:
- 接收接口返回的XML格式响应数据,解析后在界面展示物流跟踪信息
- 解析成功后自动唤起系统浏览器,跳转到对应运单的跟踪详情页
当前故障:输入错误的跟踪ID时,接口返回的XML对应目标节点为null,直接读取节点属性会触发空引用异常导致程序报错,需要实现友好的错误提示,同时阻断异常抛出。
原问题代码如下:
//ONLINE PORTAL TRACKING string ConNo = Con.Text; XmlDocument doc1 = new XmlDocument(); doc1.Load(url1 + ConNo + url2 + APIKEY); XmlElement root = doc1.DocumentElement; XmlNodeList nodes = root.SelectNodes("/Response/Detail/Data"); foreach (XmlNode node in nodes) { string ConsignmentNumber = node["ConNo"].InnerText; string tracking_url = node["tracking_url"].InnerText; string Lifts = node["Lifts"].InnerText; string TrackingID = node["TrackingID"].InnerText; string JobStatus = node["Status"].InnerText; string Barcodes = node["Barcodes"].InnerText; string Weight = node["Weight"].InnerText; string DateMan = node["DateEntered"].InnerText; this.ConsignmentNumber.Text = ConsignmentNumber; this.Lifts.Text = Lifts; // this.TrackingURL.Text = tracking_url; this.TrackingID.Text = TrackingID; this.JobStatus.Text = JobStatus; this.Barcodes.Text = Barcodes; this.Weight.Text = Weight; this.DelMan.Text = DateMan; System.Diagnostics.Process.Start(PortalURL1 + TrackingID); }
修复方案
核心逻辑是 所有XML节点取值前必须做空校验,空结果直接走错误提示分支,不执行后续业务逻辑,具体调整点:
- 接口请求、XML解析全流程包裹异常捕获,覆盖网络错误、返回格式非法等边缘场景
- 校验查询到的目标节点列表长度,长度为0时直接提示运单ID错误,终止后续流程
- 封装统一的节点取值方法,节点不存在时返回空字符串,避免直接访问null对象的
InnerText属性 - 校验核心必填字段(跟踪ID)是否为空,为空时不执行浏览器跳转逻辑,避免打开无效地址
修正后可直接运行的代码
//ONLINE PORTAL TRACKING string ConNo = Con.Text.Trim(); // 先做输入非空校验 if (string.IsNullOrEmpty(ConNo)) { MessageBox.Show("请输入有效的跟踪ID"); return; } try { XmlDocument doc1 = new XmlDocument(); doc1.Load(url1 + ConNo + url2 + APIKEY); XmlElement root = doc1.DocumentElement; // 根节点为空直接返回格式错误 if (root == null) { MessageBox.Show("接口返回格式异常,请稍后重试"); return; } XmlNodeList nodes = root.SelectNodes("/Response/Detail/Data"); // 没有匹配到数据节点,说明跟踪ID错误 if (nodes == null || nodes.Count == 0) { MessageBox.Show("未查询到对应运单信息,请检查输入的跟踪ID是否正确"); // 清空之前的界面残留数据 this.ConsignmentNumber.Text = string.Empty; this.Lifts.Text = string.Empty; this.TrackingID.Text = string.Empty; this.JobStatus.Text = string.Empty; this.Barcodes.Text = string.Empty; this.Weight.Text = string.Empty; this.DelMan.Text = string.Empty; return; } foreach (XmlNode node in nodes) { // 统一安全取值方法,节点不存在时返回空字符串 string GetNodeValue(string nodeName) { return node[nodeName]?.InnerText?.Trim() ?? string.Empty; } string ConsignmentNumber = GetNodeValue("ConNo"); string tracking_url = GetNodeValue("tracking_url"); string Lifts = GetNodeValue("Lifts"); string TrackingID = GetNodeValue("TrackingID"); string JobStatus = GetNodeValue("Status"); string Barcodes = GetNodeValue("Barcodes"); string Weight = GetNodeValue("Weight"); string DateMan = GetNodeValue("DateEntered"); // 核心字段为空时提示错误,不执行后续逻辑 if (string.IsNullOrEmpty(TrackingID)) { MessageBox.Show("运单数据解析失败,缺少核心跟踪ID字段"); return; } this.ConsignmentNumber.Text = ConsignmentNumber; this.Lifts.Text = Lifts; // this.TrackingURL.Text = tracking_url; this.TrackingID.Text = TrackingID; this.JobStatus.Text = JobStatus; this.Barcodes.Text = Barcodes; this.Weight.Text = Weight; this.DelMan.Text = DateMan; // 校验通过再打开浏览器,兼容.NET Core/.NET5+版本的启动规则 System.Diagnostics.Process.Start(new ProcessStartInfo(PortalURL1 + TrackingID) { UseShellExecute = true }); } } catch (Exception ex) { // 捕获所有请求、解析阶段的异常,给用户友好提示 MessageBox.Show($"查询失败:{ex.Message}"); }
注:.NET Core/.NET 5及以上版本调用
Process.Start打开网址时,必须显式设置UseShellExecute = true,否则会触发运行异常,上述代码已经兼容该场景。
内容的提问来源于stack exchange,提问作者LiamBetts
相关产品推荐
相关产品推荐

