如何解决System.Xml.Schema.XmlSchemaValidationException异常
UBL XML验证失败问题解决
问题场景
我尝试用ASP.NET Core控制器验证UBL格式的XML文件,使用官方提供的XSD,但始终触发以下验证错误:
System.Xml.Schema.XmlSchemaValidationException: '未声明‘urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2:UBLExtensions’元素。'
使用的XML是UBL官方示例发票文件,XSD是UBL官方的发票主XSD文件。
控制器代码
using System; using System.IO; using System.Net; using System.Xml; using System.Xml.Linq; using System.Xml.Schema; using Microsoft.AspNetCore.Mvc; namespace EINV.API.Controllers { [Route("api/[controller]")] [ApiController] public class XmlController : Controller { [HttpPost] public IActionResult ValidateXml2(IFormFile xmlFile, string xsdUrl) { XmlReaderSettings settings = new XmlReaderSettings(); settings.XmlResolver = new XmlXsdResolver(); // 用于解析include和import settings.ValidationType = ValidationType.Schema; //settings.DtdProcessing = DtdProcessing.Parse; // 有一个dtd的include,可能编译XSD后需要禁用dtd settings.Schemas.Add(null, xsdUrl); // 传入UBL发票主XSD的URL settings.Schemas.Compile(); settings.ValidationType = ValidationType.Schema; XmlReader reader = XmlReader.Create(xmlFile.OpenReadStream(), settings, "https://docs.oasis-open.org/ubl/os-UBL-2.1/xsd/maindoc/"); XmlDocument document = new XmlDocument(); document.Load(reader); ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler); document.Validate(eventHandler); return Ok(); } protected class XmlXsdResolver : XmlUrlResolver { public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) { return base.GetEntity(absoluteUri, role, ofObjectToReturn); } } private void ValidationEventHandler(object? sender, ValidationEventArgs? e) { if (e?.Severity == XmlSeverityType.Error) { throw new Exception("XML验证错误: " + e.Message); } } } }
问题原因
UBL的主XSD文件依赖多个子XSD(比如CommonExtensionComponents等),虽然代码中设置了XmlResolver,但在线加载时,依赖的XSD可能没有被正确解析并添加到验证架构集合中,或者ASP.NET Core环境的网络限制导致无法下载依赖文件。
修复方案
方案1:本地缓存UBL所有XSD文件
UBL官方XSD包含多个相互引用的文件,在线加载容易出现解析问题。建议直接下载整套UBL 2.1的XSD文件到本地项目,然后通过相对路径引用主XSD,避免网络请求的不确定性。
方案2:优化架构加载逻辑
使用XmlSchemaSet自动解析依赖的XSD,替换原来的XmlReaderSettings.Schemas方式,确保所有依赖架构被正确加载:
[HttpPost] public IActionResult ValidateXml2(IFormFile xmlFile, string xsdUrl) { XmlSchemaSet schemaSet = new XmlSchemaSet(); // 使用默认XmlUrlResolver解析依赖 schemaSet.XmlResolver = new XmlUrlResolver(); // 添加主XSD,XmlSchemaSet会自动递归加载所有import/include的依赖文件 schemaSet.Add(null, xsdUrl); // 编译架构集 schemaSet.Compile(); // 加载待验证的XML XmlDocument document = new XmlDocument(); using (var stream = xmlFile.OpenReadStream()) { document.Load(stream); } // 绑定架构集并验证 document.Schemas = schemaSet; document.Validate((sender, e) => { if (e.Severity == XmlSeverityType.Error) { throw new Exception($"XML验证错误: {e.Message}"); } }); return Ok(); }
方案3:检查网络访问权限
如果必须在线加载XSD,需要确保ASP.NET Core应用有访问外部网络的权限(比如在容器或服务器环境中,网络策略是否允许访问目标域名)。同时可以自定义XmlResolver添加日志,排查是否成功下载了依赖的XSD文件。
内容的提问来源于stack exchange,提问作者randomvoice
相关产品推荐
相关产品推荐

