.NET中验证XML时忽略schemaLocation,强制使用指定XSD
强制使用指定XSD验证XML,忽略xml中的schemaLocation属性
我实现了一个简单的XML文件验证逻辑,当XML文件不包含schemaLocation属性时验证正常,但一旦该属性存在,验证逻辑就会忽略我指定的XSD文件,转而使用该属性引用的schema。需求是:无论XML是否包含schemaLocation,都始终使用SchemaSet中指定的XSD进行验证。
原验证代码
public static bool Validate (string xmlFile, string xsdFile) { XmlReaderSettings settings = new XmlReaderSettings(); settings.Schemas.Add("", xsdFile); settings.ValidationType = ValidationType.Schema; using (XmlReader reader = XmlReader.Create(xmlFile, settings)) { XmlDocument document = new XmlDocument(); document.Load(reader); System.Console.WriteLine(settings.Schemas.Count); ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler); // the following call to Validate succeeds. document.Validate(eventHandler); } return true; } static void ValidationEventHandler(object sender, ValidationEventArgs e) { switch (e.Severity) { case XmlSeverityType.Error: throw new System.Exception(e.Message); } }
测试场景
我的目标是用指定XSD验证不同XML,理应始终抛出“Document元素不被允许”的错误:
无schemaLocation的XML(验证正常)
<?xml version="1.0" encoding="UTF-8"?> <Document> <BkToCstmrDbtCdtNtfctn xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.02"> <GrpHdr> <MsgId>TEST-fbbd57f6285403ad2b146ccbe8ceed</MsgId> <CreDtTm>2017-08-18T10:55:35.906+02:00</CreDtTm>
带schemaLocation的XML(未触发预期错误)
<?xml version="1.0" encoding="UTF-8"?> <Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.054.001.02 camt.054.001.02.xsd"> <BkToCstmrDbtCdtNtfctn xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.02"> <GrpHdr> <MsgId>TEST-fbbd57f6285403ad2b146ccbe8ceed</MsgId> <CreDtTm>2017-08-18T10:55:35.906+02:00</CreDtTm>
解决方案
要强制使用指定XSD,需要做两处关键修改:
- 禁用
ProcessSchemaLocation验证标志,阻止系统自动加载xml中指定的外部schema - 调用
XmlDocument.Validate时明确传入我们的SchemaSet,确保验证使用指定的XSD
修改后的代码
public static bool Validate(string xmlFile, string xsdFile) { XmlReaderSettings settings = new XmlReaderSettings(); settings.Schemas.Add("", xsdFile); settings.ValidationType = ValidationType.Schema; // 禁用自动处理xml中的schemaLocation属性,避免加载外部schema settings.ValidationFlags &= ~XmlSchemaValidationFlags.ProcessSchemaLocation; using (XmlReader reader = XmlReader.Create(xmlFile, settings)) { XmlDocument document = new XmlDocument(); document.Load(reader); ValidationEventHandler eventHandler = ValidationEventHandler; // 明确指定使用预先配置的SchemaSet进行验证 document.Validate(settings.Schemas, eventHandler); } return true; } static void ValidationEventHandler(object sender, ValidationEventArgs e) { if (e.Severity == XmlSeverityType.Error) { throw new Exception(e.Message); } }
关键说明
- 禁用ProcessSchemaLocation:默认情况下,
XmlReaderSettings会启用ProcessSchemaLocation标志,自动解析并加载xml中xsi:schemaLocation指定的schema。通过settings.ValidationFlags &= ~XmlSchemaValidationFlags.ProcessSchemaLocation可以关闭这一行为。 - 指定SchemaSet验证:调用
document.Validate(settings.Schemas, eventHandler)时,明确传入我们添加了指定XSD的SchemaSet,确保验证逻辑完全使用我们指定的规则,不受文档自身schema信息影响。
内容的提问来源于stack exchange,提问作者firhang
相关产品推荐
相关产品推荐

