7

我正在尝试使用带有 XDocument.Validate 扩展方法的 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 片段进行验证方面似乎可以按预期工作。

提前致谢!

4

3 回答 3

6

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

于 2012-01-24T23:01:53.580 回答
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);
于 2019-08-15T18:30:12.430 回答
0

这是一个老问题,但这是一种在创建 XDocument 实例时保留位置的方法 - 确保使用LoadOptions.SetLineInfo

XDocument.Parse(xml, LoadOptions.SetLineInfo);

然后您可以在 Validate 方法中提取位置。

于 2021-11-17T15:27:02.080 回答