我正在尝试使用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
只能包含子元素b
和c
,两者都是必需的,都是整数。我的程序给我写了下一个错误:
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.Message
和sender
,它实际上是XmlReader元素。
我的问题:有没有最好的方法以我的方式进行验证,而不解析args.Message字符串并排除考虑到巨大文件大小的内存不足异常?也许我应该使用另一个图书馆?
答案 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”进行分组,那么信息就在那里。
此外,您可以自然地按消息分组,但可能无法提供足够的分组。
当然,如果在验证时内存耗尽,这将无济于事,但至少它会提供更好的方法来处理错误类型。