使用XDocument.Validate验证Xml架构时,XmlSchemaValidationException.LineNumber和LinePosition为0

时间:2012-01-09 18:46:25

标签: c# xml xsd linq-to-xml xmlschemaset

我正在尝试使用Xml Schema和XDocument.Validate扩展方法验证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片段方面似乎按预期工作。

提前致谢!

2 个答案:

答案 0 :(得分:5)

您不再验证Xml的文本表示形式,而是验证对象模型。因此,没有行和位置,因为内存中没有文件,但XElement,XAttribute等对象。另一个有用的提示是问自己 - 如果在加载XDocument之后但在运行验证之前修改了(例如添加了elelment),应该返回什么行和位置? 如果您没有创建或修改Xml,最快的方法是使用XmlReader来验证您的Xml文档。作为奖励 - 如果输入是文件或流 - 您应该在验证错误的情况下获得行和位置信息。

答案 1 :(得分:1)

在您的ValidationEventHandler中,sender实现了IXmlLineInfo接口,该接口包含成员System.Xml.IXmlLineInfo.LineNumberSystem.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);