[英]Validate XML against XSD using Saxon API C# not reporting all validation errors
我正在尝试使用适用于 C#.Net 的 saxon api 针对 xsd 验证 xml。 但是,它并不能一次性捕获所有验证错误。 所有违反数据类型的元素都会被捕获,但如果结构形成错误且其中存在多个错误,则它只会捕获第一个错误。 我创建了如下示例代码
XSD文件
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:books" xmlns:bks="urn:books">
<xsd:element name="books" type="bks:BooksForm"/>
<xsd:complexType name="BooksForm">
<xsd:sequence>
<xsd:element name="book" type="bks:BookForm" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="BookForm">
<xsd:sequence>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="genre" type="xsd:string"/>
<xsd:element name="price" type="xsd:float" />
<xsd:element name="pub_date" type="xsd:date" />
<xsd:element name="review" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>
</xsd:schema>
文件
<?xml version="1.0"?>
<x:books xmlns:x="urn:books">
<book id="bk001">
<author>Writer</author>
<title>The First Book</title>
<genre>Fiction</genre>
<price>44.95</price>
<pub_date>2000-10-01</pub_date>
<review>An amazing story of nothing.</review>
</book>
<book id="bk002">
<author>Poet</author>
<title>The Poet's First Poem</title>
<genre>Poem</genre>
<price>ABC</price>
<review>Least poetic poems.</review>
</book>
<book id="bk003">
<bad_element_1></bad_element_1>
<bad_element_2></bad_element_2>
<author>Writer</author>
<title>The First Book</title>
<genre>Fiction</genre>
<price>ABC</price>
<pub_date>2000-10-01</pub_date>
<review>An amazing story of nothing.</review>
</book>
</x:books>
C#代码
public void run(string xmlPath, string xsdPath)
{
EnterpriseConfiguration conf = new EnterpriseConfiguration();
conf.setConfigurationProperty(FeatureKeys.LICENSE_FILE_LOCATION, @"C:\saxon\saxon-license.lic");
Processor processor = new Processor(conf);
processor.SetProperty("http://saxon.sf.net/feature/timing", "true");
processor.SetProperty("http://saxon.sf.net/feature/validation-warnings", "false"); //Set to true to suppress the exception
SchemaManager manager = processor.SchemaManager;
manager.XsdVersion = "1.1";
List<Error> errorList = new();
manager.ErrorReporter = err => errorList.Add(err);
XmlReader xsdReader = XmlReader.Create(xsdPath);
try
{
manager.Compile(xsdReader);
}
catch (Exception e)
{
Console.WriteLine(e);
Console.WriteLine("Schema compilation failed with " + errorList.Count + " errors");
foreach (Error error in errorList)
{
Console.WriteLine("At line " + error.Location.LineNumber + ": " + error.Message);
}
return;
}
SchemaValidator validator = manager.NewSchemaValidator();
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.ValidationType = ValidationType.Schema;
xmlReaderSettings.ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ReportValidationWarnings;
XmlReader xmlReader = XmlReader.Create(xmlPath, xmlReaderSettings);
Console.WriteLine("Validating input file " + xmlPath);
List<ValidationFailure> errors = new();
validator.InvalidityListener = failure => errors.Add(failure);
XdmDestination psvi = new();
validator.SetDestination(psvi);
try
{
validator.Validate(xmlReader);
}
catch (Exception e)
{
Console.WriteLine(e); Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Instance validation failed with " + errors.Count + " errors"); Console.WriteLine(); Console.WriteLine();
foreach (ValidationFailure error in errors)
{
Console.WriteLine("At line " + error.LineNumber + ": " + error.Message); Console.WriteLine(); Console.WriteLine();
}
return;
}
Console.WriteLine("Input file is valid");
}
请帮忙。 谢谢。
我希望一次性捕获所有验证错误。
通常,如果元素的内容(子元素的序列)与架构中为该元素定义的内容模型不匹配,Saxon 会将其视为一个验证错误,并且不会尝试进一步验证,直到它到达末尾无效元素。
从解析错误中恢复错误是一门艺术,没有通用的解决方案; 人们讨厌的一件事是错误地完成它会导致数百个虚假错误。
在您的特定示例中,您强调没有报告 bad_element2 的错误。 但是处理器应该如何知道什么可以有效地跟随 bad_element1? 架构没有说。 您已经偏离了规则手册,处理者无法在此处找到要应用的规则。
您可以采用架构在 bad_element1 之后不允许任何内容的方法,因此后面的任何内容都是另一个错误。 但这会导致许多您不想要的虚假错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.