我加载了一个 XML 字符串和一个架构并将其传递到一个函数中。我让它根据模式正确验证 XML,但是它总是在第一个无效元素的范围内停止验证。无效数据,它会继续下去,无效/缺失属性,会继续下去,但无效元素,它会停止,并且不会在该范围内进一步验证。
架构如下:
<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="items">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="foo">
<xs:complexType>
<xs:sequence>
<xs:element name="bar" type="xs:integer" />
<xs:element name="bat" type="xs:integer" />
</xs:sequence>
<xs:attribute name="attr1" type="xs:integer" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
xml如下:
<root>
<items>
<foo attr1='1'>
<invalid0>1</invalid0>
<invalid1>b</invalid1>
</foo>
<foo attr1='1'>
<invalid2>b</invalid2>
<bat>b</bat>
</foo>
<foo attr1='1'>
<bar>3</bar>
</foo>
<invalidFoo attr1='1'>
<bar>d</bar>
<bat>2</bat>
</invalidFoo>
<foo>
<bar>3</bar>
<bat>q</bat>
</foo>
</items>
</root>
那么,在这个例子中验证器到达第一个时会发生什么<foo>
并看到<invalid0>
并且不在范围内验证<foo>
任何进一步,因此错过<invalid1>
。验证者继续下一步<foo>
.
下一个<foo>
它看到有一个<invalid2>
它不属于那里,并且不费心去捕获无效数据<bat>
元素(字符串而不是整数)。就直接进入下一步了<foo>
它使它进入下一个<foo>
元素并抛出有关缺失的错误<bat>
并继续下一步<foo>
, cool.
现在它到了<invalidFoo>
理所当然,不会在内部进行任何验证<invalidFoo>
因为,当然,什么是<invalidFoo>
?
对我来说,症结在于,此时验证器停止验证以下所有内容<foo>
兄弟元素,所以最后的无效数据<bat>
没有被抓住。所以现在,我问的原因是因为我使用验证的方式是尝试捕获所有错误(或至少尽可能多)并将它们传递回用户。我在实际代码中所做的第一个测试相当于:
<root>
<items>
<invalidFoo attr1='1'>
<invalid0>1</invalid0>
<invalid1>b</invalid1>
</invalidFoo>
<foo attr1='1'>
<invalid2>b</invalid2>
<bat>b</bat>
</foo>
<foo attr1='1'>
<bar>3</bar>
</foo>
<invalidFoo attr1='1'>
<bar>d</bar>
<bat>2</bat>
</invalidFoo>
<foo>
<bar>3</bar>
<bat>q</bat>
</foo>
</items>
</root>
所以,验证者首先看到了这一点<invalidFoo>
然后死了。在很长一段时间里,我假设由于某种原因验证总是在出现第一个错误时停止。直到我添加了一个有效的<foo>
回来它开始连续捕获并累积其他无效数据错误。但一旦遇到无效的元素标记名,所有同级/子级验证都会被跳过。它仅发生在无效元素上,而不发生在属性或数据上。
现在,我不是说这是对还是错……我是问这是对还是错?验证器是否应该继续运行,特别是在兄弟元素的情况下?或者它应该停止并基本上根据前一个元素的无效而将整个元素列表称为无效?在这种情况下,Xml 架构验证器的预期行为是什么?
这一切都是使用以下 C# 代码完成的(其工作原理符合我的预期):
public static void ValidateAgainstSchema(string XMLSourceDocument, XmlSchemaSet validatingSchemas)
{
if (validatingSchemas == null)
{
throw new ArgumentNullException("In ValidateAgainstSchema: No schema loaded.");
}
string errorHolder = string.Empty;
ValidationHandler handler = new ValidationHandler();
XmlReaderSettings settings = new XmlReaderSettings();
settings.CloseInput = true;
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += new ValidationEventHandler(handler.HandleValidationError);
settings.Schemas.Add(validatingSchemas);
settings.ValidationFlags =
XmlSchemaValidationFlags.ReportValidationWarnings |
XmlSchemaValidationFlags.ProcessIdentityConstraints |
XmlSchemaValidationFlags.ProcessInlineSchema |
XmlSchemaValidationFlags.ProcessSchemaLocation;
StringReader srStringReader = new StringReader(XMLSourceDocument);
using (XmlReader validatingReader = XmlReader.Create(srStringReader, settings))
{
while (validatingReader.Read()) { }
}
if (handler.MyValidationErrors.Count > 0)
{
foreach (String messageItem in handler.MyValidationErrors)
{
errorHolder += messageItem;
}
throw new XmlSchemaValidationException(errorHolder);
}
}
验证事件处理程序只是捕获错误并将它们添加到IList<string>
以便稍后一起显示。