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

时间:2015-05-22 15:00:43

标签: c# xml

我正在尝试使用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元素。

我的问题:有没有最好的方法以我的方式进行验证,而不解析args.Message字符串并排除考虑到巨大文件大小的内存不足异常?也许我应该使用另一个图书馆?

1 个答案:

答案 0 :(得分:0)

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

在类

中声明几个变量
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以及Args等。

还有另一个非公共属性{{1}},它会告诉元素名称和其他信息,所以如果需要你也可以得到它。如果你想按“缺少元素X”进行分组,那么信息就在那里。

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

当然,如果在验证时内存耗尽,这将无济于事,但至少它会提供更好的方法来处理错误类型。