You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 03:45:53