XmlSchemaValidator 基于推送的验证

XmlSchemaValidator 类提供了一种高效、高性能的机制,通过基于推送的方式针对 XML 架构验证 XML 数据。 例如,使用 XmlSchemaValidator 类可以就地验证 XML 信息集,而不必将其序列化为 XML 文档,然后使用验证 XML 读取器重新分析该文档。

XmlSchemaValidator 类可以在一些高级方案中使用(例如在自定义的 XML 数据源上生成验证引擎),也可以作为生成验证 XML 写入器的一种方式。

以下示例使用 XmlSchemaValidator 类针对 contosoBooks.xml 架构验证 contosoBooks.xsd 文件。 该示例使用 XmlSerializer 类反序列化 contosoBooks.xml 文件,并将节点的值传递给 XmlSchemaValidator 类的方法。

注意

此示例在本主题的所有章节中使用。

using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Collections;

namespace Microsoft.Samples.Xml.Schema
{
    class XmlSchemaValidatorExamples
    {
        static void Main()
        {
            // The XML document to deserialize into the XmlSerializer object.
            XmlReader reader = XmlReader.Create("contosoBooks.xml");

            // The XmlSerializer object.
            XmlSerializer serializer = new XmlSerializer(typeof(ContosoBooks));
            ContosoBooks books = (ContosoBooks)serializer.Deserialize(reader);

            // The XmlSchemaSet object containing the schema used to validate the XML document.
            XmlSchemaSet schemaSet = new XmlSchemaSet();
            schemaSet.Add("http://www.contoso.com/books", "contosoBooks.xsd");

            // The XmlNamespaceManager object used to handle namespaces.
            XmlNamespaceManager manager = new XmlNamespaceManager(reader.NameTable);

            // Assign a ValidationEventHandler to handle schema validation warnings and errors.
            XmlSchemaValidator validator = new XmlSchemaValidator(reader.NameTable, schemaSet, manager, XmlSchemaValidationFlags.None);
            validator.ValidationEventHandler += new ValidationEventHandler(SchemaValidationEventHandler);

            // Initialize the XmlSchemaValidator object.
            validator.Initialize();

            // Validate the bookstore element, verify that all required attributes are present
            // and prepare to validate child content.
            validator.ValidateElement("bookstore", "http://www.contoso.com/books", null);
            validator.GetUnspecifiedDefaultAttributes(new ArrayList());
            validator.ValidateEndOfAttributes(null);

            // Get the next expected element in the bookstore context.
            XmlSchemaParticle[] particles = validator.GetExpectedParticles();
            XmlSchemaElement nextElement = particles[0] as XmlSchemaElement;
            Console.WriteLine("Expected Element: '{0}'", nextElement.Name);

            foreach (BookType book in books.Book)
            {
                // Validate the book element.
                validator.ValidateElement("book", "http://www.contoso.com/books", null);

                // Get the expected attributes for the book element.
                Console.Write("\nExpected attributes: ");
                XmlSchemaAttribute[] attributes = validator.GetExpectedAttributes();
                foreach (XmlSchemaAttribute attribute in attributes)
                {
                    Console.Write("'{0}' ", attribute.Name);
                }
                Console.WriteLine();

                // Validate the genre attribute and display its post schema validation information.
                if (book.Genre != null)
                {
                    validator.ValidateAttribute("genre", "", book.Genre, schemaInfo);
                }
                DisplaySchemaInfo();

                // Validate the publicationdate attribute and display its post schema validation information.
                if (book.PublicationDate != null)
                {
                    validator.ValidateAttribute("publicationdate", "", dateTimeGetter(book.PublicationDate), schemaInfo);
                }
                DisplaySchemaInfo();

                // Validate the ISBN attribute and display its post schema validation information.
                if (book.Isbn != null)
                {
                    validator.ValidateAttribute("ISBN", "", book.Isbn, schemaInfo);
                }
                DisplaySchemaInfo();

                // After validating all the attributes for the current element with ValidateAttribute method,
                // you must call GetUnspecifiedDefaultAttributes to validate the default attributes.
                validator.GetUnspecifiedDefaultAttributes(new ArrayList());

                // Verify that all required attributes of the book element are present
                // and prepare to validate child content.
                validator.ValidateEndOfAttributes(null);

                // Validate the title element and its content.
                validator.ValidateElement("title", "http://www.contoso.com/books", null);
                validator.ValidateEndElement(null, book.Title);

                // Validate the author element, verify that all required attributes are present
                // and prepare to validate child content.
                validator.ValidateElement("author", "http://www.contoso.com/books", null);
                validator.GetUnspecifiedDefaultAttributes(new ArrayList());
                validator.ValidateEndOfAttributes(null);

                if (book.Author.Name != null)
                {
                    // Validate the name element and its content.
                    validator.ValidateElement("name", "http://www.contoso.com/books", null);
                    validator.ValidateEndElement(null, book.Author.Name);
                }

                if (book.Author.FirstName != null)
                {
                    // Validate the first-name element and its content.
                    validator.ValidateElement("first-name", "http://www.contoso.com/books", null);
                    validator.ValidateEndElement(null, book.Author.FirstName);
                }

                if (book.Author.LastName != null)
                {
                    // Validate the last-name element and its content.
                    validator.ValidateElement("last-name", "http://www.contoso.com/books", null);
                    validator.ValidateEndElement(null, book.Author.LastName);
                }

                // Validate the content of the author element.
                validator.ValidateEndElement(null);

                // Validate the price element and its content.
                validator.ValidateElement("price", "http://www.contoso.com/books", null);
                validator.ValidateEndElement(null, book.Price);

                // Validate the content of the book element.
                validator.ValidateEndElement(null);
            }

            // Validate the content of the bookstore element.
            validator.ValidateEndElement(null);

            // Close the XmlReader object.
            reader.Close();
        }

        static XmlSchemaInfo schemaInfo = new XmlSchemaInfo();
        static object dateTimeGetterContent;

        static object dateTimeGetterHandle()
        {
            return dateTimeGetterContent;
        }

        static XmlValueGetter dateTimeGetter(DateTime dateTime)
        {
            dateTimeGetterContent = dateTime;
            return new XmlValueGetter(dateTimeGetterHandle);
        }

        static void DisplaySchemaInfo()
        {
            if (schemaInfo.SchemaElement != null)
            {
                Console.WriteLine("Element '{0}' with type '{1}' is '{2}'",
                    schemaInfo.SchemaElement.Name, schemaInfo.SchemaType, schemaInfo.Validity);
            }
            else if (schemaInfo.SchemaAttribute != null)
            {
                Console.WriteLine("Attribute '{0}' with type '{1}' is '{2}'",
                    schemaInfo.SchemaAttribute.Name, schemaInfo.SchemaType, schemaInfo.Validity);
            }
        }

        static void SchemaValidationEventHandler(object sender, ValidationEventArgs e)
        {
            switch (e.Severity)
            {
                case XmlSeverityType.Error:
                    Console.WriteLine("\nError: {0}", e.Message);
                    break;
                case XmlSeverityType.Warning:
                    Console.WriteLine("\nWarning: {0}", e.Message);
                    break;
            }
        }
    }

    [XmlRootAttribute("bookstore", Namespace = "http://www.contoso.com/books", IsNullable = false)]
    public class ContosoBooks
    {
        [XmlElementAttribute("book")]
        public BookType[] Book;
    }

    public class BookType
    {
        [XmlAttributeAttribute("genre")]
        public string Genre;

        [XmlAttributeAttribute("publicationdate", DataType = "date")]
        public DateTime PublicationDate;

        [XmlAttributeAttribute("ISBN")]
        public string Isbn;

        [XmlElementAttribute("title")]
        public string Title;

        [XmlElementAttribute("author")]
        public BookAuthor Author;

        [XmlElementAttribute("price")]
        public Decimal Price;
    }

    public class BookAuthor
    {
        [XmlElementAttribute("name")]
        public string Name;

        [XmlElementAttribute("first-name")]
        public string FirstName;

        [XmlElementAttribute("last-name")]
        public string LastName;
    }
}
Imports System.Xml
Imports System.Xml.Schema
Imports System.Xml.Serialization
Imports System.Collections


Namespace Microsoft.Samples.Xml.Schema

    Class XmlSchemaValidatorExamples

        Shared Sub Main()

            ' The XML document to deserialize into the XmlSerializer object.
            Dim reader As XmlReader = XmlReader.Create("contosoBooks.xml")

            ' The XmlSerializer object.
            Dim serializer As XmlSerializer = New XmlSerializer(GetType(ContosoBooks))
            Dim books As ContosoBooks = CType(serializer.Deserialize(reader), ContosoBooks)

            ' The XmlSchemaSet object containing the schema used to validate the XML document.
            Dim schemaSet As XmlSchemaSet = New XmlSchemaSet()
            schemaSet.Add("http://www.contoso.com/books", "contosoBooks.xsd")

            ' The XmlNamespaceManager object used to handle namespaces.
            Dim manager As XmlNamespaceManager = New XmlNamespaceManager(reader.NameTable)

            ' Assign a ValidationEventHandler to handle schema validation warnings and errors.
            Dim validator As XmlSchemaValidator = New XmlSchemaValidator(reader.NameTable, schemaSet, manager, XmlSchemaValidationFlags.None)
            'validator.ValidationEventHandler += New ValidationEventHandler(SchemaValidationEventHandler)
            AddHandler validator.ValidationEventHandler, AddressOf SchemaValidationEventHandler

            ' Initialize the XmlSchemaValidator object.
            validator.Initialize()

            ' Validate the bookstore element, verify that all required attributes are present
            ' and prepare to validate child content.
            validator.ValidateElement("bookstore", "http://www.contoso.com/books", Nothing)

            validator.GetUnspecifiedDefaultAttributes(New ArrayList())
            validator.ValidateEndOfAttributes(Nothing)

            ' Get the next expected element in the bookstore context.
            Dim particles() As XmlSchemaParticle = validator.GetExpectedParticles()
            Dim nextElement As XmlSchemaElement = particles(0)
            Console.WriteLine("Expected Element: '{0}'", nextElement.Name)

            For Each book As BookType In books.book
                ' Validate the book element.
                validator.ValidateElement("book", "http://www.contoso.com/books", Nothing)

                ' Get the expected attributes for the book element.
                Console.Write(vbCrLf & "Expected attributes: ")
                Dim attributes() As XmlSchemaAttribute = validator.GetExpectedAttributes()
                For Each attribute As XmlSchemaAttribute In attributes
                    Console.Write("'{0}' ", attribute.Name)
                Next
                Console.WriteLine()

                ' Validate the genre attribute and display its post schema validation information.
                If Not book.Genre Is Nothing Then
                    validator.ValidateAttribute("genre", "", book.Genre, schemaInfo)
                End If
                DisplaySchemaInfo()

                ' Validate the publicationdate attribute and display its post schema validation information.
                If Not book.PublicationDate = Nothing Then
                    validator.ValidateAttribute("publicationdate", "", dateTimeGetter(book.PublicationDate), schemaInfo)
                End If
                DisplaySchemaInfo()

                ' Validate the ISBN attribute and display its post schema validation information.
                If Not book.Isbn Is Nothing Then
                    validator.ValidateAttribute("ISBN", "", book.Isbn, schemaInfo)
                End If
                DisplaySchemaInfo()

                ' After validating all the attributes for the current element with ValidateAttribute method,
                ' you must call GetUnspecifiedDefaultAttributes to validate the default attributes.
                validator.GetUnspecifiedDefaultAttributes(New ArrayList())

                ' Verify that all required attributes of the book element are present
                ' and prepare to validate child content.
                validator.ValidateEndOfAttributes(Nothing)

                ' Validate the title element and its content.
                validator.ValidateElement("title", "http://www.contoso.com/books", Nothing)
                validator.ValidateEndElement(Nothing, book.Title)

                ' Validate the author element, verify that all required attributes are present
                ' and prepare to validate child content.
                validator.ValidateElement("author", "http://www.contoso.com/books", Nothing)

                validator.GetUnspecifiedDefaultAttributes(New ArrayList())
                validator.ValidateEndOfAttributes(Nothing)

                If Not book.Author.Name Is Nothing Then
                    ' Validate the name element and its content.
                    validator.ValidateElement("name", "http://www.contoso.com/books", Nothing)
                    validator.ValidateEndElement(Nothing, book.Author.Name)
                End If

                If Not book.Author.FirstName Is Nothing Then
                    ' Validate the first-name element and its content.
                    validator.ValidateElement("first-name", "http://www.contoso.com/books", Nothing)
                    validator.ValidateEndElement(Nothing, book.Author.FirstName)

                End If

                If Not book.Author.LastName Is Nothing Then
                    ' Validate the last-name element and its content.
                    validator.ValidateElement("last-name", "http://www.contoso.com/books", Nothing)
                    validator.ValidateEndElement(Nothing, book.Author.LastName)
                End If

                ' Validate the content of the author element.
                validator.ValidateEndElement(Nothing)

                ' Validate the price element and its content.
                validator.ValidateElement("price", "http://www.contoso.com/books", Nothing)
                validator.ValidateEndElement(Nothing, book.Price)

                ' Validate the content of the book element.
                validator.ValidateEndElement(Nothing)
            Next

            ' Validate the content of the bookstore element.
            validator.ValidateEndElement(Nothing)

            ' Close the XmlReader object.
            reader.Close()

        End Sub

        Shared schemaInfo As XmlSchemaInfo = New XmlSchemaInfo()
        Shared dateTimeGetterContent As Object

        Shared Function dateTimeGetterHandle() As Object

            Return dateTimeGetterContent

        End Function

        Shared Function dateTimeGetter(ByVal dateTime As DateTime) As XmlValueGetter

            dateTimeGetterContent = dateTime
            Return New XmlValueGetter(AddressOf dateTimeGetterHandle)

        End Function

        Shared Sub DisplaySchemaInfo()

            If Not schemaInfo.SchemaElement Is Nothing Then
                Console.WriteLine("Element '{0}' with type '{1}' is '{2}'", schemaInfo.SchemaElement.Name, schemaInfo.SchemaType, schemaInfo.Validity)
            ElseIf Not schemaInfo.SchemaAttribute Is Nothing Then
                Console.WriteLine("Attribute '{0}' with type '{1}' is '{2}'", schemaInfo.SchemaAttribute.Name, schemaInfo.SchemaType, schemaInfo.Validity)
            End If

        End Sub

        Shared Sub SchemaValidationEventHandler(ByVal sender As Object, ByVal e As ValidationEventArgs)

            Select Case e.Severity
                Case XmlSeverityType.Error
                    Console.WriteLine(vbCrLf & "Error: {0}", e.Message)
                    Exit Sub
                Case XmlSeverityType.Warning
                    Console.WriteLine(vbCrLf & "Warning: {0}", e.Message)
                    Exit Sub
            End Select

        End Sub

    End Class

    <XmlRootAttribute("bookstore", Namespace:="http://www.contoso.com/books", IsNullable:=False)> _
    Public Class ContosoBooks

        <XmlElementAttribute("book")> _
        Public book() As BookType

    End Class

    Public Class BookType

        <XmlAttributeAttribute("genre")> _
        Public Genre As String

        <XmlAttributeAttribute("publicationdate", DataType:="date")> _
        Public PublicationDate As DateTime

        <XmlAttributeAttribute("ISBN")> _
        Public Isbn As String

        <XmlElementAttribute("title")> _
        Public Title As String

        <XmlElementAttribute("author")> _
        Public Author As BookAuthor

        <XmlElementAttribute("price")> _
        Public Price As Decimal

    End Class

    Public Class BookAuthor

        <XmlElementAttribute("name")> _
        Public Name As String

        <XmlElementAttribute("first-name")> _
        Public FirstName As String

        <XmlElementAttribute("last-name")> _
        Public LastName As String

    End Class

End Namespace

该示例使用 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>

使用 XmlSchemaValidator 验证 XML 数据

要开始验证 XML 信息集,必须先使用 XmlSchemaValidator 构造函数初始化 XmlSchemaValidator 类的新实例。

XmlSchemaValidator 构造函数使用 XmlNameTableXmlSchemaSetXmlNamespaceManager 对象作为参数,同时也将 XmlSchemaValidationFlags 值用作参数。 XmlNameTable 对象用于原子化众所周知的命名空间字符串,例如架构命名空间、XML 命名空间等,并在验证简单内容时传递给 ParseValue 方法。 XmlSchemaSet 对象包含用于验证 XML 信息集的 XML 架构。 XmlNamespaceManager 对象用于解析在验证期间遇到的命名空间。 XmlSchemaValidationFlags 值用于禁用验证的某些功能。

有关 XmlSchemaValidator 构造函数的更多信息,请参见 XmlSchemaValidator 类参考文档。

初始化验证

构造了 XmlSchemaValidator 对象之后,有两个重载 Initialize 方法可用于初始化 XmlSchemaValidator 对象的状态。 以下是这两个 Initialize 方法。

默认的 XmlSchemaValidator.Initialize 方法将 XmlSchemaValidator 对象初始化为起始状态,使用 XmlSchemaValidator.Initialize 作为参数的重载 XmlSchemaObject 方法将 XmlSchemaValidator 对象初始化为起始状态,以进行部分验证。

这两个 Initialize 方法只能在构造了 XmlSchemaValidator 对象之后或调用了 EndValidation 之后立即调用。

有关 XmlSchemaValidator.Initialize 方法的示例,请参见简介中的示例。 有关 Initialize 方法的更多信息,请参见 XmlSchemaValidator 类参考文档。

部分验证

使用 XmlSchemaValidator.Initialize 作为参数的 XmlSchemaObject 方法将 XmlSchemaValidator 对象初始化为起始状态,以进行部分验证。

在以下示例中,使用 XmlSchemaObject 方法对 XmlSchemaValidator.Initialize 进行初始化,以进行部分验证。 在 orderNumber 对象的 XmlQualifiedName 属性返回的 XmlSchemaObjectTable 集合中,通过其中的 GlobalElements 选择架构元素,来传递 XmlSchemaSet 架构元素。 然后,XmlSchemaValidator 对象验证这个特定的元素。

Dim schemaSet As XmlSchemaSet = New XmlSchemaSet()
schemaSet.Add(Nothing, "schema.xsd")
schemaSet.Compile()
Dim nameTable As NameTable = New NameTable()
Dim manager As XmlNamespaceManager = New XmlNamespaceManager(nameTable)

Dim validator As XmlSchemaValidator = New XmlSchemaValidator(nameTable, schemaSet, manager, XmlSchemaValidationFlags.None)
validator.Initialize(schemaSet.GlobalElements.Item(New XmlQualifiedName("orderNumber")))

validator.ValidateElement("orderNumber", "", Nothing)
validator.ValidateEndOfAttributes(Nothing)
validator.ValidateText("123")
validator.ValidateEndElement(Nothing)
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.Add(null, "schema.xsd");
schemaSet.Compile();
NameTable nameTable = new NameTable();
XmlNamespaceManager manager = new XmlNamespaceManager(nameTable);

XmlSchemaValidator validator = new XmlSchemaValidator(nameTable, schemaSet, manager, XmlSchemaValidationFlags.None);
validator.Initialize(schemaSet.GlobalElements[new XmlQualifiedName("orderNumber")]);

validator.ValidateElement("orderNumber", "", null);
validator.ValidateEndOfAttributes(null);
validator.ValidateText("123");
validator.ValidateEndElement(null);

该示例使用以下 XML 架构作为输入。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="orderNumber" type="xs:int" />
</xs:schema>

有关 Initialize 方法的更多信息,请参见 XmlSchemaValidator 类参考文档。

添加其他架构

AddSchema 类的 XmlSchemaValidator 方法用于将 XML 架构添加到验证期间使用的架构集中。 AddSchema 方法可以用于模拟在所验证的 XML 信息集中遇到内联 XML 架构的效果。

注意

XmlSchema 参数的目标命名空间无法与 XmlSchemaValidator 对象已遇到的任何元素或属性的目标命名空间匹配。

如果 XmlSchemaValidationFlags.ProcessInlineSchema 值未作为参数传递给 XmlSchemaValidator 构造函数,AddSchema 方法不会执行任何操作。

AddSchema 方法的结果取决于所验证的当前 XML 节点上下文。 有关验证上下文的更多信息,请参见本主题的“验证上下文”一节。

有关 AddSchema 方法的更多信息,请参见 XmlSchemaValidator 类参考文档。

验证元素、属性和内容

XmlSchemaValidator 类提供多种方法用于针对 XML 架构验证 XML 信息集中的元素、属性和内容。 下表介绍每种方法。

方法 描述
ValidateElement 在当前上下文中验证元素名。
ValidateAttribute 在当前元素上下文中验证属性,或针对作为参数传递给 XmlSchemaAttribute 方法的 Initialize 对象验证属性。
ValidateEndOfAttributes 验证元素上下文中所有必需的属性是否已存在,并且 XmlSchemaValidator 对象是否已准备好验证元素的子内容。
ValidateText 验证当前元素上下文中是否允许包含文本,并累积文本,以验证当前元素是否包含简单内容。
ValidateWhitespace 验证当前元素上下文中是否允许包含空白,并累积空白,以验证当前元素是否包含简单内容。
ValidateEndElement 对于包含简单内容的元素,验证元素的文本内容是否符合其数据类型,对于包含复杂内容的元素,验证当前元素的内容是否完整。
SkipToEndElement 跳过当前元素内容的验证并准备 XmlSchemaValidator 对象以验证父元素的上下文中的内容。
EndValidation 如果设置了 ProcessIdentityConstraints 验证选项,结束验证并检查整个 XML 文档的标识约束。

注意

XmlSchemaValidator 类包含已定义的状态转换,强制按顺序执行对上表中所述的每种方法的调用。 XmlSchemaValidator 类特定的状态转换在本主题的“XmlSchemaValidator 状态转换”一节中介绍。

有关用于验证 XML 信息集中的元素、属性和内容的方法的示例,请参见上一节中的示例。 有关这些方法的更多信息,请参见 XmlSchemaValidator 类参考文档。

使用 XmlValueGetter 编写内容

XmlValueGetterdelegate 可用于将属性、文本或空格节点的值传递为公共语言运行时 (CLR) 类型,与属性、文本或空格节点的 XML 架构定义语言 (XSD) 类型兼容。 如果属性、文本或空格节点的 CLR 值已可用,XmlValueGetterdelegate 非常有用,这样就免去了将它转换为 string 并重新分析以供验证的成本。

ValidateAttributeValidateTextValidateWhitespace 方法是重载方法,使用属性、文本或空白节点的值作为 stringXmlValueGetterdelegate

XmlSchemaValidator 类的下列方法接受 XmlValueGetterdelegate 作为参数。

下面是从简介中的 XmlValueGetter 类示例获取的示例 delegateXmlSchemaValidatorXmlValueGetterdelegateDateTime 对象的形式返回属性的值。 要验证 DateTime 返回的此 XmlValueGetter 对象,XmlSchemaValidator 对象先将其转换为属性数据类型的 ValueType(ValueType 是该 XSD 类型默认的 CLR 映射),然后检查转换后的值的各个方面。

Shared dateTimeGetterContent As Object

Shared Function DateTimeGetterHandle() As Object
    Return dateTimeGetterContent
End Function

Shared Function DateTimeGetter(dateTime As DateTime) As XmlValueGetter
    dateTimeGetterContent = dateTime
    Return New XmlValueGetter(AddressOf DateTimeGetterHandle)
End Function
static object dateTimeGetterContent;

static object DateTimeGetterHandle()
{
    return dateTimeGetterContent;
}

static XmlValueGetter DateTimeGetter(DateTime dateTime)
{
    dateTimeGetterContent = dateTime;
    return new XmlValueGetter(dateTimeGetterHandle);
}

有关 XmlValueGetterdelegate 的完整示例,请参见简介中的示例。 若要详细了解 XmlValueGetterdelegate,请参阅 XmlValueGetterXmlSchemaValidator 类的参考文档。

后架构验证信息

XmlSchemaInfo 类表示通过 XmlSchemaValidator 类验证的 XML 节点的一些后架构验证信息。 XmlSchemaValidator 类的各种方法使用 XmlSchemaInfo 对象作为可选的 (null) out 参数。

在成功地验证之后,XmlSchemaInfo 对象的属性将使用验证结果进行设置。 例如,使用 ValidateAttribute 方法成功地验证某个属性之后,XmlSchemaInfo 对象的(如果指定)SchemaAttributeSchemaTypeMemberTypeValidity 属性将使用验证结果进行设置。

下列 XmlSchemaValidator 类方法使用 XmlSchemaInfo 对象作为输出参数。

有关 XmlSchemaInfo 类的完整示例,请参见简介中的示例。 有关 XmlSchemaInfo 类的更多信息,请参见 XmlSchemaInfo 类参考文档。

检索预计的粒子、属性和未指定的默认属性

XmlSchemaValidator 类提供 GetExpectedAttributesGetExpectedParticlesGetUnspecifiedDefaultAttributes 方法来检索当前验证上下文中预计的粒子、属性和未指定的默认属性。

检索预计的粒子

GetExpectedParticles 方法返回一个 XmlSchemaParticle 对象数组,包含当前元素上下文中预计的粒子。 GetExpectedParticles 方法可以返回的有效粒子是 XmlSchemaElementXmlSchemaAny 类的实例。

如果内容模型的复合器是 xs:sequence,则只返回序列中的下一个粒子。 如果内容模型的复合器是 xs:allxs:choice,则返回当前元素上下文中可能出现的所有有效粒子。

注意

如果 GetExpectedParticles 方法在调用 Initialize 方法之后立即调用,GetExpectedParticles 方法将返回所有全局元素。

例如,在下面的 XML 架构定义语言 (XSD) 架构和 XML 文档中,在验证 book 元素之后,book 元素是当前的元素上下文。 GetExpectedParticles 方法返回一个数组,包含表示 XmlSchemaElement 元素的单个 title 对象。 如果验证上下文是 title 元素,GetExpectedParticles 方法将返回一个空数组。 如果 GetExpectedParticles 方法在验证了 title 元素之后但是在验证 description 元素之前调用,将返回一个数组,包含表示 XmlSchemaElement 元素的单个 description 对象。 如果 GetExpectedParticles 方法在验证了 description 元素之后调用,将返回一个数组,包含表示通配符的单个 XmlSchemaAny 对象。

Dim reader As XmlReader =  XmlReader.Create("input.xml")

Dim schemaSet As New XmlSchemaSet()
schemaSet.Add(Nothing, "schema.xsd")
Dim manager As New XmlNamespaceManager(reader.NameTable)

Dim validator As New XmlSchemaValidator(reader.NameTable,schemaSet,manager,XmlSchemaValidationFlags.None)
validator.Initialize()

validator.ValidateElement("book", "", Nothing)

validator.ValidateEndOfAttributes(Nothing)
For Each element As XmlSchemaElement In validator.GetExpectedParticles()
    Console.WriteLine(element.Name)
Next

validator.ValidateElement("title", "", Nothing)
validator.ValidateEndOfAttributes(Nothing)
For Each element As XmlSchemaElement In validator.GetExpectedParticles()
    Console.WriteLine(element.Name)
Next
validator.ValidateEndElement(Nothing)

For Each element As XmlSchemaElement In validator.GetExpectedParticles()
    Console.WriteLine(element.Name)
Next

validator.ValidateElement("description", "", Nothing)
validator.ValidateEndOfAttributes(Nothing)
validator.ValidateEndElement(Nothing)

For Each particle As XmlSchemaParticle In validator.GetExpectedParticles()
    Console.WriteLine(particle.GetType())
Next

validator.ValidateElement("namespace", "", Nothing)
validator.ValidateEndOfAttributes(Nothing)
validator.ValidateEndElement(Nothing)

validator.ValidateEndElement(Nothing)
XmlReader reader = XmlReader.Create("input.xml");

var schemaSet = new XmlSchemaSet();
schemaSet.Add(null, "schema.xsd");
var manager = new XmlNamespaceManager(reader.NameTable);

var validator = new XmlSchemaValidator(reader.NameTable, schemaSet, manager, XmlSchemaValidationFlags.None);
validator.Initialize();

validator.ValidateElement("book", "", null);

validator.ValidateEndOfAttributes(null);
foreach (XmlSchemaElement element in validator.GetExpectedParticles())
{
    Console.WriteLine(element.Name);
}

validator.ValidateElement("title", "", null);
validator.ValidateEndOfAttributes(null);
foreach (XmlSchemaElement element in validator.GetExpectedParticles())
{
    Console.WriteLine(element.Name);
}
validator.ValidateEndElement(null);

foreach (XmlSchemaElement element in validator.GetExpectedParticles())
{
    Console.WriteLine(element.Name);
}

validator.ValidateElement("description", "", null);
validator.ValidateEndOfAttributes(null);
validator.ValidateEndElement(null);

foreach (XmlSchemaParticle particle in validator.GetExpectedParticles())
{
    Console.WriteLine(particle.GetType());
}

validator.ValidateElement("namespace", "", null);
validator.ValidateEndOfAttributes(null);
validator.ValidateEndElement(null);

validator.ValidateEndElement(null);

该示例使用以下 XML 作为输入:

<xs:schema xmlns:xs="http://www.w3c.org/2001/XMLSchema">
  <xs:element name="book">
    <xs:sequence>
      <xs:element name="title" type="xs:string" />
      <xs:element name="description" type="xs:string" />
      <xs:any processContent="lax" maxOccurs="unbounded" />
    </xs:sequence>
  </xs:element>
</xs:schema>

该示例使用以下 XSD 架构作为输入:

<book>
  <title>My Book</title>
  <description>My Book's Description</description>
  <namespace>System.Xml.Schema</namespace>
</book>

注意

GetExpectedParticles 类的 GetExpectedAttributesAddSchemaXmlSchemaValidator 方法的结果取决于正在验证的当前上下文。 有关更多信息,请参见本主题的“验证上下文”一节。

有关 GetExpectedParticles 方法的示例,请参见简介中的示例。 有关 GetExpectedParticles 方法的更多信息,请参见 XmlSchemaValidator 类参考文档。

检索预计的属性

GetExpectedAttributes 方法返回一个 XmlSchemaAttribute 对象数组,包含当前元素上下文中预计的属性。

例如,在简介的示例中,GetExpectedAttributes 方法用于检索 book 元素的所有属性。

如果在调用 GetExpectedAttributes 方法之后立即调用 ValidateElement 方法,将返回 XML 文档中可能出现的所有属性。 但是,如果在一次或多次调用 GetExpectedAttributes 方法之后调用 ValidateAttribute 方法,将返回当前元素尚未进行验证的属性。

注意

GetExpectedParticles 类的 GetExpectedAttributesAddSchemaXmlSchemaValidator 方法的结果取决于正在验证的当前上下文。 有关更多信息,请参见本主题的“验证上下文”一节。

有关 GetExpectedAttributes 方法的示例,请参见简介中的示例。 有关 GetExpectedAttributes 方法的更多信息,请参见 XmlSchemaValidator 类参考文档。

检索未指定的默认属性

GetUnspecifiedDefaultAttributes 方法使用元素上下文中以前尚未使用 ArrayList 方法进行验证的默认值填充使用任何属性的 XmlSchemaAttribute 对象指定的 ValidateAttributeGetUnspecifiedDefaultAttributes 方法应在元素上下文中的每个属性上调用了 ValidateAttribute 方法之后调用。 GetUnspecifiedDefaultAttributes 方法应用于确定要插入正在验证的 XML 文档的默认属性。

有关 GetUnspecifiedDefaultAttributes 方法的更多信息,请参见 XmlSchemaValidator 类参考文档。

处理架构验证事件

在验证过程中遇到的架构验证警告和错误由 ValidationEventHandler 类的 XmlSchemaValidator 事件进行处理。

架构验证警告的 XmlSeverityType 值为 Warning,架构验证错误的 XmlSeverityType 值为 Error。 如果尚未分配任何 ValidationEventHandler,所有 XmlSchemaValidationException 值为 XmlSeverityType 的架构验证错误将引发 Error。 但是,XmlSchemaValidationException 值为 XmlSeverityType 的架构验证警告不会引发 Warning

以下 ValidationEventHandler 示例接收在架构验证过程中遇到的架构验证警告和错误,该示例从简介的示例中获取。

Shared Sub SchemaValidationEventHandler(sender As Object, e As ValidationEventArgs)

    Select Case e.Severity
        Case XmlSeverityType.Error
            Console.WriteLine(vbCrLf & "Error: {0}", e.Message)
            Exit Sub
        Case XmlSeverityType.Warning
            Console.WriteLine(vbCrLf & "Warning: {0}", e.Message)
            Exit Sub
    End Select
End Sub
static void SchemaValidationEventHandler(object sender, ValidationEventArgs e)
{
    switch (e.Severity)
    {
        case XmlSeverityType.Error:
            Console.WriteLine("\nError: {0}", e.Message);
            break;
        case XmlSeverityType.Warning:
            Console.WriteLine("\nWarning: {0}", e.Message);
            break;
    }
}

有关 ValidationEventHandler 的完整示例,请参见简介中的示例。 有关更多信息,请参见 XmlSchemaInfo 类参考文档。

XmlSchemaValidator 状态转换

XmlSchemaValidator 类包含已定义的状态转换,强制按顺序执行对用于验证 XML 信息集中的元素、属性和内容的每种方法的调用。

下表介绍 XmlSchemaValidator 类的状态转换以及每个状态可以按顺序执行的方法调用。

状态 切换
Validate Initialize (ValidateAttribute | TopLevel*) EndValidation
TopLevel ValidateWhitespace | ValidateText | Element
元素 ValidateElement ValidateAttribute* (ValidateEndOfAttributes Content)? ValidateEndElement |

ValidateElement ValidateAttribute* SkipToEndElement |

ValidateElement ValidateAttribute* ValidateEndOfAttributes Content* SkipToEndElement |
内容 ValidateWhitespace | ValidateText | Element

注意

如果调用方法的顺序不符合 InvalidOperationException 对象的当前状态,上表中的每种方法将引发 XmlSchemaValidator

上面的状态转换表使用标点符号描述 XmlSchemaValidator 类中状态转换的每种状态可以调用的方法和其他状态。 使用的符号与文档类型定义 (DTD) 的 XML 标准引用中出现的符号相同。

下表描述上面的状态转换表中出现的标点符号如何影响 XmlSchemaValidator 类中状态转换的每种状态可以调用的方法和其他状态。

符号 说明
| 可以调用(竖线之前或竖线之后的)方法或状态。
问号之前的方法或状态是可选的,但是如果调用,只能调用一次。
* \* 符号之前的方法或状态是可选的,可以调用多次。

验证上下文

XmlSchemaValidator 类中用于验证 XML 信息集中的元素、属性和内容的方法会更改 XmlSchemaValidator 对象的验证上下文。 例如,SkipToEndElement 方法跳过当前元素内容的验证并准备 XmlSchemaValidator 对象,以验证父元素上下文中的内容;这等效于跳过当前元素的所有子级的验证并调用 ValidateEndElement 方法。

GetExpectedParticles 类的 GetExpectedAttributesAddSchemaXmlSchemaValidator 方法的结果取决于正在验证的当前上下文。

下表介绍在调用 XmlSchemaValidator 类中的一个用于验证 XML 信息集中的元素、属性和内容的方法之后调用这些方法的结果。

方法 GetExpectedParticles GetExpectedAttributes AddSchema
Initialize 如果调用默认的 Initialize 方法,GetExpectedParticles 将返回包含所有全局元素的数组。

如果调用使用 Initialize 作为参数的重载 XmlSchemaObject 方法来初始化元素的部分验证,GetExpectedParticles 将只返回 XmlSchemaValidator 对象初始化所针对的元素。
如果调用默认的 Initialize 方法,GetExpectedAttributes 将返回一个空数组。

如果调用使用 Initialize 作为参数的重载 XmlSchemaObject 方法来初始化属性的部分验证,GetExpectedAttributes 将只返回 XmlSchemaValidator 对象初始化所针对的属性。
如果没有预处理错误,将架构添加到 XmlSchemaSet 对象的 XmlSchemaValidator 中。
ValidateElement 如果上下文元素有效,GetExpectedParticles 将返回预计作为上下文元素子级的元素序列。

如果上下文元素无效,GetExpectedParticles 将返回一个空数组。
如果上下文元素有效,并且以前未调用过 ValidateAttributeGetExpectedAttributes 将返回上下文元素上定义的所有属性的列表。

如果某些属性已进行验证,GetExpectedAttributes 将返回其他要验证的属性的列表。

如果上下文元素无效,GetExpectedAttributes 将返回一个空数组。
同上。
ValidateAttribute 如果上下文属性是顶级属性,GetExpectedParticles 将返回一个空数组。

否则,GetExpectedParticles 将返回预计作为上下文元素的第一个子级的元素序列。
如果上下文属性是顶级属性,GetExpectedAttributes 将返回一个空数组。

否则,GetExpectedAttributes 将返回其他要验证的属性的列表。
同上。
GetUnspecifiedDefaultAttributes GetExpectedParticles 将返回需要作为上下文元素的第一个子级的元素的序列。 GetExpectedAttributes 将返回仍需要验证的上下文元素的必选属性和可选属性的列表。 同上。
ValidateEndOfAttributes GetExpectedParticles 将返回需要作为上下文元素的第一个子级的元素的序列。 GetExpectedAttributes 将返回一个空数组。 同上。
ValidateText 如果上下文元素的 contentType 为 Mixed,GetExpectedParticles 将返回下一个位置预计的元素序列。

如果上下文元素的 contentType 为 TextOnly 或 Empty,GetExpectedParticles 将返回一个空数组。

如果上下文元素的 contentType 为 ElementOnly,GetExpectedParticles 将返回下一个位置预计的、但是已出现验证错误的元素序列。
GetExpectedAttributes 将返回未验证的上下文元素属性列表。 同上。
ValidateWhitespace 如果上下文空白是顶级空白,GetExpectedParticles 将返回一个空数组。

否则,GetExpectedParticles 方法的行为与 ValidateText 中相同。
如果上下文空白是顶级空白,GetExpectedAttributes 将返回一个空数组。

否则,GetExpectedAttributes 方法的行为与 ValidateText 中相同。
同上。
ValidateEndElement GetExpectedParticles 返回上下文元素之后预计的元素序列(可能是同级)。 GetExpectedAttributes 将返回未验证的上下文元素属性列表。

如果上下文元素没有父级,GetExpectedAttributes 将返回一个空列表(上下文元素是调用 ValidateEndElement 的当前元素的父级)。
同上。
SkipToEndElement ValidateEndElement 相同。 ValidateEndElement 相同。 同上。
EndValidation 返回一个空数组。 返回一个空数组。 同上。

注意

调用上表中的任何方法时不会更改 XmlSchemaValidator 类的各种属性返回的值。

请参阅