大型xml验证和分组失败消息

本文关键字:失败 消息 xml 验证 大型 | 更新日期: 2023-09-27 17:50:34

我正在尝试使用xsd-schema验证大型xml文件。下面是我的代码:

    void Validate()
    {
        var settings = new XmlReaderSettings();
        settings.Schemas.Add(null, selectedXsd);
        settings.ValidationType = ValidationType.Schema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
        settings.ValidationEventHandler += ValidationCallBack;
        var reader = XmlReader.Create(selectedXml, settings);
        while (reader.Read()) {}
    }
    public void ValidationCallBack(object sender, ValidationEventArgs args)
    {
        Console.WriteLine(args.Message);
    }

下面是我的示例xml文件:

<root>
    <a>
        <b>1</b>
        <c>two</c>
    </a>
    <a>
        <b>1</b>
    </a>
    <a>
        <b>1</b>
        <c>2</c>
        <d>3</d>
    </a>
</root>

存在已定义的强模式规则。元素a只能包含子元素bc,它们都是必需的,并且都是整数。我的程序给我写了以下错误:

The 'c' element is invalid - The value 'two' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:int' - The string 'two' is not a valid Integer value.
The element 'a' has incomplete content. List of possible elements expected: 'b, c'.
The element 'a' has invalid child element 'd'. List of possible elements expected: 'b, c'

看起来很好,但问题是文件大小大(> 2gb),可能有数千个错误。当特定元素的值无效时,它应该"分组"这些错误,不管它们的值是多少。当元素丢失时,它应该对错误进行适当的分组,甚至可能计算它们丢失的次数。当不同的节点中缺少不同的元素时,它应该报告另一个错误。以此类推所有可能的错误。但它只有信息是字符串args.Messagesender,这实际上是XmlReader元素。

我的问题:有没有最好的方法来做验证在我的方式,不解析参数。消息字符串和排除内存不足的异常考虑巨大的文件大小?也许我应该用另一个图书馆?

大型xml验证和分组失败消息

如果你能接受一个有一点反思的解决方案,并希望按一般错误(无效的元素,不正确的类型等)分组,你可以这样做:

在类

中声明两个变量
Dictionary<string, List<XmlSchemaException>> exps = new Dictionary<string, List<XmlSchemaException>>();
PropertyInfo ErrorGetResProp;

在验证方法中找到非公共属性:

ErrorGetResProp = typeof(XmlSchemaValidationException).GetProperty("GetRes", BindingFlags.NonPublic | BindingFlags.Instance);

然后在验证回调中你可以收集错误:

string error = ErrorGetResProp.GetValue(args.Exception) as string;
List<XmlSchemaException> e = null;
if (!exps.TryGetValue(error, out e))
  exps[error] = e = new List<XmlSchemaException>();
e.Add(args.Exception);

之后,你有一个字典exps,其中包含Keys中所有不同的错误类型(没有很快找到关于可能值的文档,但它可以很容易地手动收集)。字典中的值将提供错误,因此您可以轻松地Count()它们,或显示Message,以及LineNumber s等。

还有另一个非公共属性Args,它将告诉元素名称和其他信息,因此如果需要,您也可以获取这些信息。如果你想按"element X missing"分组,信息就在那里。

您也可以自然地按消息分组,但它可能无法提供足够的分组。

当然,如果在验证时内存耗尽,这将没有帮助,但至少它将提供一种更好的处理错误类型的方法。