驗證 DOM 中的 XML 文件

依預設,XmlDocument 類別不會根據 XML 結構描述定義語言 (XSD) 結構描述或文件類型定義 (DTD) 來驗證文件物件模型 (DOM) 中的 XML;其只會驗證 XML 的格式是否正確。

若要驗證 DOM 中的 XML,您可以在將 XML 載入到 DOM 時,藉由將結構描述驗證的 XmlReader 傳遞至 Load 類別的 XmlDocument 方法來驗證它,也可使用 Validate 類別的 XmlDocument 方法,驗證 DOM 中先前未驗證的 XML 文件。

將 XML 文件載入到 DOM 時進行驗證

在將驗證 XmlDocument 傳遞至 XmlReader 類別的 Load 方法時,XmlDocument 類別會在 XML 資料載入 DOM 時加以驗證。

在驗證成功之後,會套用結構描述預設值,視需要將文字值轉換成原子值,並將類型資訊與已驗證的資訊項目相關聯。 因此,具類型的 XML 資料會取代先前不具類型的 XML 資料。

建立 XML 結構描述驗證的 XmlReader

若要建立 XML 結構描述驗證的 XmlReader,請遵循下列步驟。

  1. 建構新的 XmlReaderSettings 執行個體。

  2. 將 XML 結構描述加入至 Schemas 執行個體的 XmlReaderSettings 屬性。

  3. 指定 Schema 做為 ValidationType

  4. 選擇性地指定 ValidationFlagsValidationEventHandler,以處理驗證期間遇到的結構描述驗證錯誤及警告。

  5. 最後,將 XmlReaderSettings 物件傳遞至 Create 類別的 XmlReader 方法,及傳遞至 XML 文件,建立結構描述驗證的 XmlReader

範例

在下面的程式碼範例中,結構描述驗證的 XmlReader 會驗證載入至 DOM 的 XML 資料。 對 XML 文件進行無效的修改,然後重新驗證該文件,會導致結構描述驗證錯誤。 最後,更正其中一個錯誤,然後對 XML 文件的一部分進行部分驗證。

#using <System.Xml.dll>

using namespace System;
using namespace System::Xml;
using namespace System::Xml::Schema;

ref class XmlDocumentValidationExample
{
public:

    static void Main()
    {
        try
        {
            // Create a schema validating XmlReader.
            XmlReaderSettings^ settings = gcnew XmlReaderSettings();
            settings->Schemas->Add("http://www.contoso.com/books", "contosoBooks.xsd");
            ValidationEventHandler^ eventHandler = gcnew ValidationEventHandler(ValidationEventHandlerOne);
            settings->ValidationEventHandler += eventHandler;
            settings->ValidationFlags = settings->ValidationFlags | XmlSchemaValidationFlags::ReportValidationWarnings;
            settings->ValidationType = ValidationType::Schema;

            XmlReader^ reader = XmlReader::Create("contosoBooks.xml", settings);

            // The XmlDocument validates the XML document contained
            // in the XmlReader as it is loaded into the DOM.
            XmlDocument^ document = gcnew XmlDocument();
            document->Load(reader);

            // Make an invalid change to the first and last 
            // price elements in the XML document, and write
            // the XmlSchemaInfo values assigned to the price
            // element during load validation to the console.
            XmlNamespaceManager^ manager = gcnew XmlNamespaceManager(document->NameTable);
            manager->AddNamespace("bk", "http://www.contoso.com/books");

            XmlNode^ priceNode = document->SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager);

            Console::WriteLine("SchemaInfo.IsDefault: {0}", priceNode->SchemaInfo->IsDefault);
            Console::WriteLine("SchemaInfo.IsNil: {0}", priceNode->SchemaInfo->IsNil);
            Console::WriteLine("SchemaInfo.SchemaElement: {0}", priceNode->SchemaInfo->SchemaElement);
            Console::WriteLine("SchemaInfo.SchemaType: {0}", priceNode->SchemaInfo->SchemaType);
            Console::WriteLine("SchemaInfo.Validity: {0}", priceNode->SchemaInfo->Validity);

            priceNode->InnerXml = "A";

            XmlNodeList^ priceNodes = document->SelectNodes("/bk:bookstore/bk:book/bk:price", manager);
            XmlNode^ lastprice = priceNodes[priceNodes->Count - 1];
            
            lastprice->InnerXml = "B";

            // Validate the XML document with the invalid changes.
            // The invalid changes cause schema validation errors.
            document->Validate(eventHandler);

            // Correct the invalid change to the first price element.
            priceNode->InnerXml = "8.99";

            // Validate only the first book element. The last book
            // element is invalid, but not included in validation.
            XmlNode^ bookNode = document->SelectSingleNode("/bk:bookstore/bk:book", manager);
            document->Validate(eventHandler, bookNode);
        }
        catch (XmlException^ ex)
        {
            Console::WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex->Message);
        }
        catch(XmlSchemaValidationException^ ex)
        {
            Console::WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex->Message);
        }
        catch (Exception^ ex)
        {
            Console::WriteLine("XmlDocumentValidationExample.Exception: {0}", ex->Message);
        }
    }

    static void ValidationEventHandlerOne(Object^ sender, ValidationEventArgs^ args)
    {
        if (args->Severity == XmlSeverityType::Warning)
            Console::Write("\nWARNING: ");
        else if (args->Severity == XmlSeverityType::Error)
            Console::Write("\nERROR: ");

        Console::WriteLine(args->Message);
    }
};

int main()
{
    XmlDocumentValidationExample::Main();
    return 0;
}
using System;
using System.Xml;
using System.Xml.Schema;

class XmlDocumentValidationExample
{
    static void Main(string[] args)
    {
        try
        {
            // Create a schema validating XmlReader.
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandler);
            settings.ValidationFlags = settings.ValidationFlags | XmlSchemaValidationFlags.ReportValidationWarnings;
            settings.ValidationType = ValidationType.Schema;

            XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);

            // The XmlDocument validates the XML document contained
            // in the XmlReader as it is loaded into the DOM.
            XmlDocument document = new XmlDocument();
            document.Load(reader);

            // Make an invalid change to the first and last
            // price elements in the XML document, and write
            // the XmlSchemaInfo values assigned to the price
            // element during load validation to the console.
            XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
            manager.AddNamespace("bk", "http://www.contoso.com/books");

            XmlNode priceNode = document.SelectSingleNode(@"/bk:bookstore/bk:book/bk:price", manager);

            Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault);
            Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil);
            Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement);
            Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType);
            Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity);

            priceNode.InnerXml = "A";

            XmlNodeList priceNodes = document.SelectNodes(@"/bk:bookstore/bk:book/bk:price", manager);
            XmlNode lastprice = priceNodes[priceNodes.Count - 1];

            lastprice.InnerXml = "B";

            // Validate the XML document with the invalid changes.
            // The invalid changes cause schema validation errors.
            document.Validate(ValidationEventHandler);

            // Correct the invalid change to the first price element.
            priceNode.InnerXml = "8.99";

            // Validate only the first book element. The last book
            // element is invalid, but not included in validation.
            XmlNode bookNode = document.SelectSingleNode(@"/bk:bookstore/bk:book", manager);
            document.Validate(ValidationEventHandler, bookNode);
        }
        catch (XmlException ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message);
        }
        catch(XmlSchemaValidationException ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message);
        }
    }

    static void ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs args)
    {
        if (args.Severity == XmlSeverityType.Warning)
            Console.Write("\nWARNING: ");
        else if (args.Severity == XmlSeverityType.Error)
            Console.Write("\nERROR: ");

        Console.WriteLine(args.Message);
    }
}
Imports System.Xml
Imports System.Xml.Schema

Class XmlDocumentValidationExample

    Shared Sub Main()

        Try

            ' Create a schema validating XmlReader.
            Dim settings As XmlReaderSettings = New XmlReaderSettings()
            settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")
            AddHandler settings.ValidationEventHandler, New ValidationEventHandler(AddressOf ValidationEventHandler)
            settings.ValidationFlags = settings.ValidationFlags And XmlSchemaValidationFlags.ReportValidationWarnings
            settings.ValidationType = ValidationType.Schema

            Dim reader As XmlReader = XmlReader.Create("contosoBooks.xml", settings)

            ' The XmlDocument validates the XML document contained
            ' in the XmlReader as it is loaded into the DOM.
            Dim document As XmlDocument = New XmlDocument()
            document.Load(reader)

            ' Make an invalid change to the first and last 
            ' price elements in the XML document, and write
            ' the XmlSchemaInfo values assigned to the price
            ' element during load validation to the console.
            Dim manager As XmlNamespaceManager = New XmlNamespaceManager(document.NameTable)
            manager.AddNamespace("bk", "http://www.contoso.com/books")

            Dim priceNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager)

            Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault)
            Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil)
            Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement)
            Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType)
            Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity)

            priceNode.InnerXml = "A"

            Dim priceNodes As XmlNodeList = document.SelectNodes("/bk:bookstore/bk:book/bk:price", manager)
            Dim lastprice As XmlNode = priceNodes(priceNodes.Count - 1)

            lastprice.InnerXml = "B"

            ' Validate the XML document with the invalid changes.
            ' The invalid changes cause schema validation errors.
            document.Validate(AddressOf ValidationEventHandler)

            ' Correct the invalid change to the first price element.
            priceNode.InnerXml = "8.99"

            ' Validate only the first book element. The last book
            ' element is invalid, but not included in validation.
            Dim bookNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book", manager)
            document.Validate(AddressOf ValidationEventHandler, bookNode)

        Catch ex As XmlException
            Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message)

        Catch ex As XmlSchemaValidationException
            Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message)

        Catch ex As Exception
            Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message)

        End Try

    End Sub

    Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)

        If args.Severity = XmlSeverityType.Warning Then
            Console.Write(vbCrLf & "WARNING: ")
        Else
            If args.Severity = XmlSeverityType.Error Then
                Console.Write(vbCrLf & "ERROR: ")
            End If
        End If
        Console.WriteLine(args.Message)

    End Sub

End Class

該範例採用 contosoBooks.xml 檔案做為輸入。

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
    <book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
            <first-name>Benjamin</first-name>
            <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
    </book>
    <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
        <title>The Confidence Man</title>
        <author>
            <first-name>Herman</first-name>
            <last-name>Melville</last-name>
        </author>
        <price>11.99</price>
    </book>
    <book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
        <title>The Gorgias</title>
        <author>
            <name>Plato</name>
        </author>
        <price>9.99</price>
    </book>
</bookstore>

該範例還將 contosoBooks.xsd 檔案做為輸入。

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.contoso.com/books" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="bookstore">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="book">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="title" type="xs:string" />
                            <xs:element name="author">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element minOccurs="0" name="name" type="xs:string" />
                                        <xs:element minOccurs="0" name="first-name" type="xs:string" />
                                        <xs:element minOccurs="0" name="last-name" type="xs:string" />
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                            <xs:element name="price" type="xs:decimal" />
                        </xs:sequence>
                        <xs:attribute name="genre" type="xs:string" use="required" />
                        <xs:attribute name="publicationdate" type="xs:date" use="required" />
                        <xs:attribute name="ISBN" type="xs:string" use="required" />
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

在驗證載入至 DOM 的 XML 資料時,請考量下列事項。

  • 在上述範例中,每當遇到無效的類型時,就會呼叫 ValidationEventHandler。 如果 ValidationEventHandler 未在要進行驗證的 XmlReader 中設定,若因任何屬性或項目與要進行驗證之結構描述中指定的對應類型不符合,而呼叫 XmlSchemaValidationException 時,則會擲回 Load

  • 當 XML 文件載入至具有可定義預設值之關聯結構描述的 XmlDocument 物件時,XmlDocument 會處理這些預設值,就好像它們是出現在 XML 文件中。 這表示 IsEmptyElement 屬性針對該結構描述預設會產生的項目,永遠傳回 false。 即使在 XML 文件中,它也做為空白項目寫入。

驗證 DOM 中的 XML 文件

根據 Validate 物件之 XmlDocument 屬性中的結構描述,XmlDocument 類別的 Schemas 方法會驗證載入到 DOM 的 XML 資料。 在驗證成功之後,會套用結構描述預設值,視需要將文字值轉換成原子值,並將類型資訊與已驗證的資訊項目相關聯。 因此,具類型的 XML 資料會取代先前不具類型的 XML 資料。

以下範例與上述<將 XML 文件載入到 DOM 時進行驗證>中的範例相似。 在此範例中,XML 文件不是在載入到 DOM 時進行驗證,而是在載入到 DOM 之後,使用 Validate 類別的 XmlDocument 方法進行驗證。 Validate 方法會根據 SchemasXmlDocument 屬性中包含的 XML 結構描述,驗證 XML 文件。 然後對 XML 文件進行無效的修改並重新驗證該文件,會導致結構描述驗證錯誤。 最後,更正其中一個錯誤,然後對 XML 文件的一部分進行部分驗證。

using System;
using System.Xml;
using System.Xml.Schema;

class XmlDocumentValidationExample
{
    static void Main(string[] args)
    {
        try
        {
            // Create a new XmlDocument instance and load
            // the XML document into the DOM.
            XmlDocument document = new XmlDocument();
            document.Load("contosoBooks.xml");

            // Add the XML schema for the XML document to the
            // Schemas property of the XmlDocument.
            document.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");

            // Validate the XML document loaded into the DOM.
            document.Validate(ValidationEventHandler);

            // Make an invalid change to the first and last
            // price elements in the XML document, and write
            // the XmlSchemaInfo values assigned to the price
            // element during validation to the console.
            XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
            manager.AddNamespace("bk", "http://www.contoso.com/books");

            XmlNode priceNode = document.SelectSingleNode(@"/bk:bookstore/bk:book/bk:price", manager);

            Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault);
            Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil);
            Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement);
            Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType);
            Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity);

            priceNode.InnerXml = "A";

            XmlNodeList priceNodes = document.SelectNodes(@"/bk:bookstore/bk:book/bk:price", manager);
            XmlNode lastprice = priceNodes[priceNodes.Count - 1];

            lastprice.InnerXml = "B";

            // Validate the XML document with the invalid changes.
            // The invalid changes cause schema validation errors.
            document.Validate(ValidationEventHandler);

            // Correct the invalid change to the first price element.
            priceNode.InnerXml = "8.99";

            // Validate only the first book element. The last book
            // element is invalid, but not included in validation.
            XmlNode bookNode = document.SelectSingleNode(@"/bk:bookstore/bk:book", manager);
            document.Validate(ValidationEventHandler, bookNode);
        }
        catch (XmlException ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message);
        }
        catch(XmlSchemaValidationException ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message);
        }
    }

    static void ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs args)
    {
        if (args.Severity == XmlSeverityType.Warning)
            Console.Write("\nWARNING: ");
        else if (args.Severity == XmlSeverityType.Error)
            Console.Write("\nERROR: ");

        Console.WriteLine(args.Message);
    }
}
Imports System.Xml
Imports System.Xml.Schema

Class XmlDocumentValidationExample

    Shared Sub Main()

        Try

            ' Create a new XmlDocument instance and load
            ' the XML document into the DOM.
            Dim document As XmlDocument = New XmlDocument()
            document.Load("contosoBooks.xml")

            ' Add the XML schema for the XML document to the
            ' Schemas property of the XmlDocument.
            document.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")

            ' Validate the XML document loaded into the DOM.
            document.Validate(AddressOf ValidationEventHandler)

            ' Make an invalid change to the first and last 
            ' price elements in the XML document, and write
            ' the XmlSchemaInfo values assigned to the price
            ' element during validation to the console.
            Dim manager As XmlNamespaceManager = New XmlNamespaceManager(document.NameTable)
            manager.AddNamespace("bk", "http://www.contoso.com/books")

            Dim priceNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager)

            Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault)
            Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil)
            Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement)
            Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType)
            Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity)

            priceNode.InnerXml = "A"

            Dim priceNodes As XmlNodeList = document.SelectNodes("/bk:bookstore/bk:book/bk:price", manager)
            Dim lastprice As XmlNode = priceNodes(priceNodes.Count - 1)

            lastprice.InnerXml = "B"

            ' Validate the XML document with the invalid changes.
            ' The invalid changes cause schema validation errors.
            document.Validate(AddressOf ValidationEventHandler)

            ' Correct the invalid change to the first price element.
            priceNode.InnerXml = "8.99"

            ' Validate only the first book element. The last book
            ' element is invalid, but not included in validation.
            Dim bookNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book", manager)
            document.Validate(AddressOf ValidationEventHandler, bookNode)

        Catch ex As XmlException
            Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message)

        Catch ex As XmlSchemaValidationException
            Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message)

        Catch ex As Exception
            Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message)

        End Try

    End Sub

    Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)

        If args.Severity = XmlSeverityType.Warning Then
            Console.Write(vbCrLf & "WARNING: ")
        Else
            If args.Severity = XmlSeverityType.Error Then
                Console.Write(vbCrLf & "ERROR: ")
            End If
        End If
        Console.WriteLine(args.Message)

    End Sub

End Class

該範例將上述<將 XML 文件載入到 DOM 時進行驗證>所指的 contosoBooks.xmlcontosoBooks.xsd 檔案當做輸入。

處理驗證錯誤及警告

驗證載入 DOM 中的 XML 資料時,會報告 XML 結構描述驗證錯誤。 會通知您在驗證載入的 XML 資料時,或者驗證先前未驗證的 XML 文件時,所找到的全部結構描述錯誤。

驗證錯誤由 ValidationEventHandler 來處理。 如果將 ValidationEventHandler 指派給 XmlReaderSettings 執行個體,或傳遞至 Validate 類別的 XmlDocument 方法,則 ValidationEventHandler 將處理結構描述驗證錯誤;否則當遇到結構描述驗證錯誤時,會引發 XmlSchemaValidationException

注意

除非 ValidationEventHandler 引發例外狀況並停止處理序,否則即使發生結構描述驗證錯誤,也會將 XML 資料載入到 DOM。

除非將 ReportValidationWarnings 旗標指定至 XmlReaderSettings 物件,否則不會報告結構描述驗證警告。

如需說明 ValidationEventHandler 的範例,請參閱上述<將 XML 文件載入到 DOM 時進行驗證>及<驗證 DOM 中的 XML 文件>。

另請參閱