如何在.NET中获取XML文件的全部XSD验证错误
问题说明
- 接触.NET时间尚短,对平台提供的各类可用库不够熟悉
- 此前使用Java开发了一款函数应用,目前需要移植到C#。现阶段使用.NET内置的XSD验证库已经可以完成XML文件的基础校验,但将校验结果和Java版本对比时发现,.NET版本上报的验证错误数量远少于Java版本
根XSD文件示例
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns="schema_namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="schema_namespace" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:include schemaLocation="included_xsd_1.xsd"/> <xs:include schemaLocation="included_xsd_2.xsd"/> <xs:include schemaLocation="included_xsd_3.xsd"/> <xs:include schemaLocation="included_xsd_4.xsd"/> <xs:include schemaLocation="included_xsd_5.xsd"/> <xs:element name="DEMDataSet"> <xs:annotation> <xs:documentation>Root Tag</xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="dCustomElement" type="dCustomElement" id="dElementSection" minOccurs="0"> <xs:annotation> <xs:documentation>Contains information for custom elements.</xs:documentation> </xs:annotation> </xs:element> <xs:element name="Report" id="ReportGroup" maxOccurs="unbounded"> <xs:annotation> <xs:documentation>Container Tag to hold each instance of a record</xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="from_included_xsd_1" type="type" id="typeSection"> <xs:annotation> <xs:documentation>Some Information</xs:documentation> </xs:annotation> </xs:element> <xs:element name="from_included_2" type="type" id="typeSection" minOccurs="0"> <xs:annotation> <xs:documentation>Some Information</xs:documentation> </xs:annotation> </xs:element> ... </xs:sequence> <xs:attribute name="timeStamp" type="DateTimeType" use="required"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
问题现象
当某个被引入的XSD文件对应内容存在缺失元素时,该XSD对应部分后续的所有错误都不会被上报:例如如果首个元素缺失,该XSD文件对应的其他验证错误都会被跳过,校验逻辑会直接转到下一个引入的XSD继续执行。
校验代码参考微软官方文档编写,实现如下:
public XsdValidationResult ValidateXml(string filePath) { var schemas = GetSchemas(); var settings = new XmlReaderSettings(); settings.Schemas.Add(schemas); settings.ValidationType = ValidationType.Schema; settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings; settings.ValidationEventHandler += XsdValidationEventHandler; using var reader = XmlReader.Create(filePath, settings); var doc = new XmlDocument { PreserveWhitespace = true }; doc.Load(reader); return GetValidationResult(); } private void XsdValidationEventHandler(object sender, ValidationEventArgs e) { if (e.Severity != XmlSeverityType.Error) return; var sb = new StringBuilder(); sb.Append(e.Message); sb.Append($" Line Number: {e.Exception.LineNumber}"); sb.Append($" Position: {e.Exception.LinePosition}"); _errors.Add(sb.ToString()); }
目前能获取到的验证错误示例如下,输出该错误后校验就会跳转到下一个schema:
命名空间“namespace”下的元素“subSchema.elementGroup”包含无效的子元素“subSchema.element02”。预期的可能元素列表为:命名空间“namespace”下的“subSchema.element03”。
微软文档中记载的XmlReader默认行为说明:
当新的XmlReader关闭后,原始XmlReader会定位在子树的EndElement节点上。也就是说,如果在book元素的开始标签上调用ReadSubtree方法,子树读取完成、新XmlReader关闭后,原始XmlReader会定位在book元素的结束标签上。
该默认行为不符合实际需求,需要确认是否存在可行方案(无论是使用.NET内置库还是第三方库),可以在发现缺失元素等验证错误后继续解析XML文件,从而捕获全部XSD验证错误。
内容的提问来源于stack exchange,提问作者esotericbob
相关产品推荐
相关产品推荐

