簡體   English   中英

使用 Saxon API C# 根據 XSD 驗證 XML 不報告所有驗證錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM