使用XDocument.Validate验证Xml架构时,XmlSchemaValidationException.Li
本文关键字:XmlSchemaValidationException Li XDocument Validate 验证 Xml 使用 | 更新日期: 2023-09-27 18:19:47
我正在尝试使用带有XDocument.Valide扩展方法的Xml架构来验证Xml片段。无论何时使用无效的Xml片段,ValidationEventHandler都会正确激发,但是XmlSchemaValidationException的LineNumber和LinePosition属性都为0。
private bool Validate(XDocument doc)
{
bool isValid = true;
List<string> validationErrors = new List<string>();
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(null, "MyCustomSchema.xsd");
doc.Validate(schemas, (sender, args) =>
{
validationErrors.Add(String.Format("{0}: {1} [Ln {2} Col {3}]",
args.Severity,
args.Exception.Message,
args.Exception.LineNumber,
args.Exception.LinePosition));
isValid = false;
}, false);
return isValid;
}
在上面的例子中,我的目标是使用validationErrors来通知用户验证失败的原因。但是,使用此方法时,LineNumber和LinePosition都为0。
该片段似乎足够简单,并且在针对有效和无效的Xml片段进行验证方面似乎可以按预期工作。
提前感谢!
您不再验证Xml的文本表示,而是验证对象模型。结果是没有行和位置,因为内存中除了XElement、XAttribute等对象之外没有文件。另一个有用的提示是问问自己——如果在加载XDocument之后但在运行验证之前修改(例如添加了一个element)XDocument,那么应该返回哪行和位置?如果您没有创建或修改Xml,最快的方法是使用XmlReader来验证Xml文档。额外的好处是,如果输入是一个文件或流,您应该在验证错误的情况下获得行和位置信息。
在ValidationEventHandler
中,sender
实现IXmlLineInfo
接口,该接口包含成员System.Xml.IXmlLineInfo.LineNumber
和System.Xml.IXmlLineInfo.LinePosition
所以你可以这样做:
doc.Validate(schemas, (sender, args) =>
{
var lineInfo = sender as IXmlLineInfo;
validationErrors.Add(String.Format("{0}: {1} [Ln {2} Col {3}]",
args.Severity,
args.Exception.Message,
lineInfo?.LineNumber,
lineInfo?.LinePosition));
isValid = false;
}, false);
这是一个老问题,但这里有一种方法可以在创建XDocument实例时保留位置-确保使用LoadOptions.SetLineInfo
XDocument.Parse(xml, LoadOptions.SetLineInfo);
然后可以在Validate方法中提取位置。