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

为何C#中XSD未自动触发必填字段等验证异常?

XML校验异常问题排查与解决

我的XML文件存在以下不符合XSD规则的问题:

  • 部分<Record>元素缺失必填的logical属性
  • is_city_saver属性使用了"Yes"而非合法布尔值true/false
  • 部分logical属性值为非数字(如"dt")

但使用C#代码校验时,XML竟通过了验证,未抛出任何错误,调试时还出现attributeSchemaInfo空引用异常,现分析原因并给出解决办法。

待校验的XML文件

<?xml version="1.0" encoding="utf-8"?>
<Zones xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.keaneaustralia.com/Nts" xsi:schemaLocation="http://schemas.keaneaustralia.com/Nts Zones.xsd" version="1" major_version="434" minor_version="0" start_date="2023-07-09T00:00:00+10:00">
<Record long_desc="City Saver Zone"/>
<Record logical="2" physical="1" short_desc="Zone 1" long_desc="Zone 1" is_city_saver="Yes" />
<Record logical="3" physical="2" short_desc="Zone 2" long_desc="Zone 2" is_city_saver="false" />
<Record logical="dt" physical="3" short_desc="Zone 3" long_desc="Zone 3" is_city_saver="false" />
<Record logical="5" physical="4" short_desc="Zone 4" long_desc="Zone 4" is_city_saver="false" />
<Record logical="6" physical="5" short_desc="Zone 5" long_desc="Zone 5" is_city_saver="false" />
</Zones>

对应的XSD Schema

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://schemas.keaneaustralia.com/Nts" elementFormDefault="qualified" targetNamespace="http://schemas.keaneaustralia.com/Nts" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Zones" nillable="true" type="tns:ZoneCollection" />
<xs:complexType name="ZoneCollection">
<xs:complexContent mixed="false">
<xs:extension base="tns:DataElementOfZone" />
</xs:complexContent>
</xs:complexType>
<xs:complexType name="DataElementOfZone">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Record" type="tns:Zone" />
</xs:sequence>
<xs:attribute name="version" type="xs:int" use="required" />
<xs:attribute name="major_version" type="xs:int" use="required" />
<xs:attribute name="minor_version" type="xs:int" use="required" />
<xs:attribute name="start_date" type="xs:dateTime" use="required" />
<xs:attribute default="false" name="is_delta" type="xs:boolean" />
<xs:attribute default="0" name="delta_major_version" type="xs:int" />
<xs:attribute default="0" name="delta_minor_version" type="xs:int" />
</xs:complexType>
<xs:complexType name="Zone">
<xs:attribute name="logical" type="xs:unsignedByte" use="required" />
<xs:attribute name="physical" type="xs:unsignedByte" use="required" />
<xs:attribute name="short_desc" type="xs:string" />
<xs:attribute name="long_desc" type="xs:string" />
<xs:attribute name="is_city_saver" type="xs:boolean" use="required" />
</xs:complexType>
</xs:schema>

用于校验的C#代码

private static bool ValidateXmlAgainstXsd(string xmlFilePath, string xsdFilePath, ILogger fileLogger)
{
    try
    {
        int numErreur = 0;
        XmlSchemaSet schemaSet = new XmlSchemaSet();
        schemaSet.Add(null, xsdFilePath);
        schemaSet.Compile();

        XmlReaderSettings settings = new XmlReaderSettings();
        settings.Schemas.Add(schemaSet);
        settings.ValidationType = ValidationType.Schema;
        settings.ValidationFlags =
        XmlSchemaValidationFlags.ReportValidationWarnings |
        XmlSchemaValidationFlags.ProcessIdentityConstraints |
        XmlSchemaValidationFlags.ProcessInlineSchema;
        settings.ValidationEventHandler += (sender, e) =>
        {
           LogValidationError(xmlFilePath, e.Message, e.Exception, e.Exception.LineNumber, e.Exception.LinePosition, e.Severity, fileLogger, ref numErreur);
        };

        using (XmlReader reader = XmlReader.Create(xmlFilePath, settings))
        {
            while (reader.Read())
            {
                //process code
             }
        }
        return numErreur > 0 ? false : true;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error validating XML '{xmlFilePath}' against XSD '{xsdFilePath}': {ex.Message}");
        return false;
    }
}

问题原因分析

  1. 命名空间匹配错误:
    XSD中Record元素属于目标命名空间http://schemas.keaneaustralia.com/Nts,但代码中XmlSchemaSet.Add(null, xsdFilePath)未指定命名空间,导致校验器无法将XML中的Record与XSD中的tns:Zone类型关联,直接跳过了属性规则校验。

  2. ValidationFlags缺少关键选项:
    未启用XmlSchemaValidationFlags.ProcessSchemaLocation,校验器会忽略XML中的xsi:schemaLocation声明,影响Schema关联的完整性。

  3. attributeSchemaInfo空引用:
    当校验器未正确关联Schema时,reader.AttributeSchemaInfo返回null,若调试时直接访问该属性会触发空引用异常。

解决办法

1. 修正Schema集合的命名空间关联

将schemaSet.Add(null, xsdFilePath)改为指定XSD的目标命名空间,确保校验器能正确匹配XML元素:

schemaSet.Add("http://schemas.keaneaustralia.com/Nts", xsdFilePath);

2. 补充ValidationFlags必要选项

添加ProcessSchemaLocation,确保校验器处理XML中的Schema位置声明:

settings.ValidationFlags =
XmlSchemaValidationFlags.ReportValidationWarnings |
XmlSchemaValidationFlags.ProcessIdentityConstraints |
XmlSchemaValidationFlags.ProcessInlineSchema |
XmlSchemaValidationFlags.ProcessSchemaLocation;

3. 修复日志方法中的空引用问题

在LogValidationError调用前,先判断e.Exception是否为null,避免空引用:

int lineNumber = e.Exception?.LineNumber ?? 0;
int linePosition = e.Exception?.LinePosition ?? 0;
LogValidationError(xmlFilePath, e.Message, e.Exception, lineNumber, linePosition, e.Severity, fileLogger, ref numErreur);

4. 验证修正效果

修改后重新校验XML,会正确触发以下错误:

  • 第一个<Record>缺失logical、physical、is_city_saver必填属性
  • 第二个<Record>的is_city_saver="Yes"不符合布尔值格式
  • 第四个<Record>的logical="dt"不符合xs:unsignedByte类型要求

内容的提问来源于stack exchange,提问作者Ayushi Ramsurn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 15:44:51