使用C#解析XML文件时遇到Null值解析错误的求助
解决XML解析中含xsi:nil="true"节点的类型转换错误
问题场景
在C#解析XML文件时,遍历Measurement节点过程中,遇到标记为xsi:nil="true"的SensorBlobVersion空节点,触发Input string was not in a correct format错误。现有代码仅判断元素是否为null,无法处理这种存在但标记为nil的节点,导致类型转换失败。
源XML示例
<XMLList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <measList> <Measurement> <MeasurementGuid>87ae41e0-e9ec-4570-83c1-75fbfc96db17</MeasurementGuid> <SequenceNumber>953</SequenceNumber> <Time>2020-10-07T15:39:06</Time> <SensorBlobVersion xsi:nil="true" /> </Measurement> <Measurement> <MeasurementGuid>1243234-e9ec-2324-83c1-43fbfc96db17</MeasurementGuid> <SequenceNumber>111</SequenceNumber> <Time>2022-11-07T15:39:06</Time> <SensorBlobVersion xsi:nil="true" /> </Measurement> </measList> </XMLList>
报错的C#示例代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace XMLFileUploader { using System.Linq; using System.Xml; using System.Xml.Linq; namespace XMLFileUploader { public static class ExtractLogFile { public static void ExtractData(string filePath) { XElement root = XElement.Load(filePath); IEnumerable<XElement> tests = from el in root.Elements("measList") select el; IEnumerable<XElement> measList = from el2 in tests.Elements("Measurement") select el2; foreach (XElement el2 in measList) { Measurement mes = new Measurement(); if (el2.NodeType == XmlNodeType.Element && el2.Name == "Measurement") { mes.MeasurementInfoGuid = (String)el2.Element("MeasurementGuid"); mes.SequenceNumber = (int)el2.Element("SequenceNumber"); mes.Time = (DateTime)el2.Element("Time"); if (el2.Element("SensorBlobVersion") == null) { mes.SensorBlobVersion = 0; } else { mes.SensorBlobVersion = (int?)(el2.Element("SensorBlobVersion")); // **ERROR AT THIS LINE** } } } } public class Measurement { public String MeasurementInfoGuid { get; set; } public int SequenceNumber { get; set; } public DateTime Time { get; set; } public int? SensorBlobVersion { get; set; } } } } }
原因分析
带xsi:nil="true"的节点并非null,它是一个实际存在的元素,只是通过XML Schema的nil标记声明其值为空。直接对该元素执行(int?)强制转换时,由于元素没有有效文本内容,会触发格式转换错误。
解决方案
方法1:检查节点的nil标记
判断元素是否存在,同时检查其是否带有xsi:nil="true"属性,再决定赋值逻辑:
var sensorBlobVersionEl = el2.Element("SensorBlobVersion"); if (sensorBlobVersionEl == null || (bool?)sensorBlobVersionEl.Attribute(XName.Get("nil", "http://www.w3.org/2001/XMLSchema-instance")) == true) { mes.SensorBlobVersion = 0; // 或赋值为null,根据业务需求调整 } else { mes.SensorBlobVersion = (int)sensorBlobVersionEl; }
方法2:利用LINQ to XML的隐式转换特性
LINQ to XML对带有xsi:nil="true"的元素,执行(int?)转换会直接返回null,因此可以简化为:
mes.SensorBlobVersion = (int?)el2.Element("SensorBlobVersion") ?? 0;
如果业务允许SensorBlobVersion为null,甚至可以直接写:
mes.SensorBlobVersion = (int?)el2.Element("SensorBlobVersion");
方法3:封装扩展方法复用判断逻辑
如果需要频繁处理这类nil节点,可以封装扩展方法:
public static class XElementExtensions { public static bool IsNil(this XElement element) { if (element == null) return false; var nilAttr = element.Attribute(XName.Get("nil", "http://www.w3.org/2001/XMLSchema-instance")); return nilAttr != null && (bool)nilAttr; } }
使用时:
var sensorEl = el2.Element("SensorBlobVersion"); mes.SensorBlobVersion = sensorEl.IsNil() ? 0 : (int)sensorEl;
修改后的完整代码示例
using System; using System.Collections.Generic; using System.Linq; using System.Xml; using System.Xml.Linq; namespace XMLFileUploader { public static class ExtractLogFile { public static void ExtractData(string filePath) { XElement root = XElement.Load(filePath); var measList = root.Element("measList")?.Elements("Measurement") ?? Enumerable.Empty<XElement>(); foreach (XElement el2 in measList) { Measurement mes = new Measurement(); mes.MeasurementInfoGuid = (string)el2.Element("MeasurementGuid"); mes.SequenceNumber = (int)el2.Element("SequenceNumber"); mes.Time = (DateTime)el2.Element("Time"); // 使用简化的转换逻辑 mes.SensorBlobVersion = (int?)el2.Element("SensorBlobVersion") ?? 0; } } public class Measurement { public string MeasurementInfoGuid { get; set; } public int SequenceNumber { get; set; } public DateTime Time { get; set; } public int? SensorBlobVersion { get; set; } } } }
内容的提问来源于stack exchange,提问作者skt
相关产品推荐
相关产品推荐

