如何解决XML检查中的System.Xml.XmlException: '根元素缺失'错误?
解决XML验证时“根元素缺失”的问题
错误原因
你代码里的核心问题是复用了已被读取完毕的StringReader实例:
- 第一次用
srStringReader创建XmlReader并执行InferSchema时,已经把整个XML内容读完,流的位置停在了末尾。 - 第二次再用同一个
srStringReader创建reader1时,没有任何内容可以读取,自然触发“根元素缺失”的异常。
修复方案
方案1:重新创建StringReader
每次读取前新建一个StringReader实例,确保每次都从XML内容的开头读取:
using System.Text; using System.Xml; using System.Xml.Schema; using XmlParser3; string doc = Resource1.Payload; XmlDocument document = new XmlDocument(); var errors = new StringBuilder(); // 第一次读取用于推断Schema XmlReaderSettings settings = new XmlReaderSettings(); settings.CloseInput = true; settings.ValidationType = ValidationType.Schema; using (var srForSchema = new StringReader(doc)) using (XmlReader reader = XmlReader.Create(srForSchema)) { XmlSchemaSet schemaSet = new XmlSchemaSet(); XmlSchemaInference schema = new XmlSchemaInference(); schemaSet = schema.InferSchema(reader); settings.Schemas.Add(schemaSet); settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings | XmlSchemaValidationFlags.ProcessIdentityConstraints | XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ProcessSchemaLocation; } // 第二次读取用于加载和验证XML,新建StringReader using (var srForValidation = new StringReader(doc)) using (var reader1 = XmlReader.Create(srForValidation, settings)) { document.Load(reader1); document.Validate((o, e) => { errors.AppendLine(e.Exception?.Message ?? e.Message); }); } Console.WriteLine(errors);
方案2:用MemoryStream重置读取位置
StringReader没法直接重置位置,可以换成MemoryStream承载XML内容,通过Seek方法把流指针移回开头:
using System.Text; using System.Xml; using System.Xml.Schema; using XmlParser3; string doc = Resource1.Payload; byte[] xmlBytes = Encoding.UTF8.GetBytes(doc); using (var ms = new MemoryStream(xmlBytes)) { XmlDocument document = new XmlDocument(); var errors = new StringBuilder(); XmlReaderSettings settings = new XmlReaderSettings(); settings.CloseInput = false; // 不关闭流,留着复用 settings.ValidationType = ValidationType.Schema; // 第一次读取推断Schema using (XmlReader reader = XmlReader.Create(ms)) { XmlSchemaSet schemaSet = new XmlSchemaSet(); XmlSchemaInference schema = new XmlSchemaInference(); schemaSet = schema.InferSchema(reader); settings.Schemas.Add(schemaSet); settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings | XmlSchemaValidationFlags.ProcessIdentityConstraints | XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ProcessSchemaLocation; } // 重置流到开头 ms.Seek(0, SeekOrigin.Begin); // 第二次读取验证XML using (var reader1 = XmlReader.Create(ms, settings)) { document.Load(reader1); document.Validate((o, e) => { errors.AppendLine(e.Exception?.Message ?? e.Message); }); } Console.WriteLine(errors); }
关于“逐行检查XML格式合规”的补充
如果你的需求是只检查XML语法格式(不是基于Schema的验证),可以调整配置关闭Schema验证,直接逐行检查:
using System.Text; using System.Xml; using System.Xml.Schema; using XmlParser3; string doc = Resource1.Payload; var errors = new StringBuilder(); XmlReaderSettings syntaxCheckSettings = new XmlReaderSettings(); syntaxCheckSettings.ValidationType = ValidationType.None; syntaxCheckSettings.ValidationEventHandler += (o, e) => { errors.AppendLine($"行 {e.Exception.LineNumber}:{e.Message}"); }; using (var sr = new StringReader(doc)) using (XmlReader reader = XmlReader.Create(sr, syntaxCheckSettings)) { try { while (reader.Read()) { } } catch (XmlException ex) { errors.AppendLine($"行 {ex.LineNumber}:{ex.Message}"); } } Console.WriteLine(errors);
内容的提问来源于stack exchange,提问作者loki
相关产品推荐
相关产品推荐

