Поделиться через


Принудительная проверка с помощью XmlSchemaValidator

Класс XmlSchemaValidator предоставляет эффективный механизм с высокой производительностью для проверки XML-данных в стиле push на соответствие 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: '{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 '{schemaInfo.SchemaElement.Name}' with type '{schemaInfo.SchemaType}' is '{schemaInfo.Validity}'");
            }
            else if (schemaInfo.SchemaAttribute != null)
            {
                Console.WriteLine($"Attribute '{schemaInfo.SchemaAttribute.Name}' with type '{schemaInfo.SchemaType}' is '{schemaInfo.Validity}'");
            }
        }

        static void SchemaValidationEventHandler(object sender, ValidationEventArgs e)
        {
            switch (e.Severity)
            {
                case XmlSeverityType.Error:
                    Console.WriteLine($"\nError: {e.Message}");
                    break;
                case XmlSeverityType.Warning:
                    Console.WriteLine($"\nWarning: {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>

Проверка XML-данных с помощью XmlSchemaValidator

Чтобы начать проверку набора сведений XML, необходимо сначала инициализировать новый экземпляр класса XmlSchemaValidator с помощью конструктора XmlSchemaValidator.

Конструктор XmlSchemaValidator принимает XmlNameTable, XmlSchemaSetи XmlNamespaceManager объекты в качестве параметров, а также значение 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 Завершает проверку и проверяет валидационные ограничения идентификаторов для всего XML-документа, если установлена опция валидации ProcessIdentityConstraints.

Примечание.

Класс XmlSchemaValidator имеет определенный переход состояния, который обеспечивает соблюдение последовательности и порядка вызовов для каждого из методов, описанных в предыдущей таблице. Конкретный переход состояния класса XmlSchemaValidator описан в разделе "Переход состояния XmlSchemaValidator" этого раздела.

Пример методов, используемых для проверки элементов, атрибутов и содержимого в xml-наборе сведений, см. в примере в предыдущем разделе. Дополнительные сведения об этих методах см. в справочной документации по классу XmlSchemaValidator.

Проверка содержимого с помощью XmlValueGetter

XmlValueGetter delegate можно использовать для передачи значений узлов атрибута, текста или пробельных символов в виде типов Общего языка исполнения (CLR), совместимых с типом языка определения схем XML (XSD) атрибута, текста или пробельного символа. XmlValueGetter delegate полезно, если значение CLR для атрибута, текста или узла пробела уже доступно, что позволяет избежать затрат на преобразование его в string и последующий повторный анализ для проверки.

Методы ValidateAttribute, ValidateTextи ValidateWhitespace перегружены и принимают значение узлов атрибута, текста или пробела в виде string или XmlValueGetterdelegate.

Следующие методы класса XmlSchemaValidator принимают XmlValueGetterdelegate в качестве параметра.

Ниже приведен пример XmlValueGetterdelegate, взятый из примера класса XmlSchemaValidator во введении. XmlValueGetter delegate возвращает значение атрибута в виде объекта DateTime. Чтобы проверить этот объект DateTime, возвращаемый XmlValueGetter, объект XmlSchemaValidator сначала преобразует его в ValueType (ValueType — это сопоставление CLR по умолчанию для типа XSD) для типа данных атрибута, а затем проверяет аспекты преобразованного значения.

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см. в справочной документации по классу XmlValueGetterи классу XmlSchemaValidator.

После схемы—Validation-Information

Класс XmlSchemaInfo представляет Post-Schema-Validation-Information XML-узла, проверенного классом XmlSchemaValidator. Различные методы класса XmlSchemaValidator принимают объект XmlSchemaInfo в качестве необязательного параметра (null) out.

После успешной проверки свойства объекта XmlSchemaInfo задаются с результатами проверки. Например, при успешной проверке атрибута с помощью метода ValidateAttribute, свойства SchemaAttribute, SchemaType, MemberTypeи Validity объекта XmlSchemaInfo (если указан) устанавливаются результатами этой проверки.

Следующие методы класса XmlSchemaValidator принимают объект XmlSchemaInfo в качестве параметра out.

Полный пример класса XmlSchemaInfo см. в этом примере. Дополнительные сведения о классе XmlSchemaInfo см. в справочной документации по классу XmlSchemaInfo.

Получение ожидаемых частиц, атрибутов и неопределенных атрибутов по умолчанию

Класс XmlSchemaValidator предоставляет методы GetExpectedAttributes, GetExpectedParticlesи GetUnspecifiedDefaultAttributes для получения ожидаемых частиц, атрибутов и неопределенных атрибутов по умолчанию в текущем контексте проверки.

Получение ожидаемых частиц

Метод GetExpectedParticles возвращает массив объектов XmlSchemaParticle, содержащих ожидаемые частицы в текущем контексте элемента. Допустимые частицы, которые могут быть возвращены методом GetExpectedParticles, являются экземплярами классов XmlSchemaElement и XmlSchemaAny.

Когда компостатор для модели содержимого является xs:sequence, возвращается только следующая частица в последовательности. Если компостатор для модели содержимого является xs:all или xs: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, GetExpectedAttributesи AddSchema методов класса XmlSchemaValidator зависят от текущего контекста, проверяемого. Дополнительные сведения см. в разделе "Контекст проверки" этой статьи.

Пример метода GetExpectedParticles см. в введении. Дополнительные сведения о методе GetExpectedParticles см. в справочной документации по классу XmlSchemaValidator.

Получение ожидаемых атрибутов

Метод GetExpectedAttributes возвращает массив объектов XmlSchemaAttribute, содержащих ожидаемые атрибуты в текущем контексте элемента.

Например, в примере в вводном примере метод GetExpectedAttributes используется для получения всех атрибутов элемента book.

При вызове метода GetExpectedAttributes сразу после метода ValidateElement возвращаются все атрибуты, которые могут отображаться в XML-документе. Однако при вызове метода GetExpectedAttributes после одного или нескольких вызовов метода ValidateAttribute возвращаются атрибуты, которые еще не проверены для текущего элемента.

Примечание.

Результаты GetExpectedParticles, GetExpectedAttributesи AddSchema методов класса XmlSchemaValidator зависят от текущего контекста, проверяемого. Дополнительные сведения см. в разделе "Контекст проверки" этой статьи.

Пример метода GetExpectedAttributes см. в введении. Дополнительные сведения о методе GetExpectedAttributes см. в справочной документации по классу XmlSchemaValidator.

Получение неопределенных атрибутов по умолчанию

Метод GetUnspecifiedDefaultAttributes заполняет ArrayList объектами XmlSchemaAttribute в контексте элемента для любых атрибутов со значениями по умолчанию, которые ранее не были проверены с помощью метода ValidateAttribute. Метод GetUnspecifiedDefaultAttributes должен вызываться после вызова метода ValidateAttribute для каждого атрибута в контексте элемента. Метод GetUnspecifiedDefaultAttributes следует использовать для определения того, какие атрибуты по умолчанию необходимо вставить в проверяемый XML-документ.

Дополнительные сведения о методе GetUnspecifiedDefaultAttributes см. в справочной документации по классу XmlSchemaValidator.

Обработка событий проверки схемы

Предупреждения и ошибки проверки схемы, возникающие во время проверки, обрабатываются событием ValidationEventHandler класса XmlSchemaValidator.

Предупреждения проверки схемы имеют значение XmlSeverityTypeWarning, а ошибки проверки схемы имеют значение XmlSeverityTypeError. Если 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, а также последовательность и частота вызовов методов, которые можно выполнить в каждом состоянии.

Государство Переход
Подтвердить Initialize (ValidateAttribute | TopLevel*) EndValidation
Верхний уровень ValidateWhitespace | ValidateText | Элемент
Элемент ValidateElement ValidateAttribute* (ValidateEndOfAttributes Содержимое*)? ValidateEndElement |

ValidateElement ValidateAttribute * SkipToEndElement |

ValidateElement ValidateAttribute * ValidateEndOfAttributes содержимое* SkipToEndElement |
Содержимое ValidateWhitespace | ValidateText | Элемент

Примечание.

InvalidOperationException создается каждым из методов в таблице выше, когда вызов метода выполняется в неправильной последовательности в соответствии с текущим состоянием объекта XmlSchemaValidator.

В приведенной выше таблице перехода состояния используются символы препинания для описания методов и других состояний, которые можно вызывать для каждого состояния перехода состояния класса XmlSchemaValidator. Используемые символы являются одинаковыми символами, найденными в справочнике по стандартам XML для определения типа документа (DTD).

В следующей таблице описывается, как символы препинания, найденные в таблице перехода состояния выше, влияют на методы и другие состояния, которые можно вызывать для каждого состояния в переходе состояния класса XmlSchemaValidator.

Символ Описание
| Можно вызвать либо метод, либо состояние (перед чертой или после неё).
? Метод или состояние, предшествующее знаку вопроса, является необязательным, но если оно вызывается, то может быть вызвано только один раз.
* Метод или состояние, предшествующие символу *, является необязательным и может вызываться несколько раз.

Контекст проверки

Методы класса XmlSchemaValidator, используемого для проверки элементов, атрибутов и содержимого в наборе сведений XML, изменяют контекст проверки объекта XmlSchemaValidator. Например, метод SkipToEndElement пропускает проверку текущего содержимого элемента и подготавливает объект XmlSchemaValidator для проверки содержимого в контексте родительского элемента; Это эквивалентно пропускать проверку для всех дочерних элементов текущего элемента, а затем вызывать метод ValidateEndElement.

Результаты GetExpectedParticles, GetExpectedAttributesи AddSchema методов класса XmlSchemaValidator зависят от текущего контекста, проверяемого.

В следующей таблице описываются результаты вызова этих методов после вызова одного из методов класса XmlSchemaValidator, используемого для проверки элементов, атрибутов и содержимого в наборе сведений XML.

Метод GetExpectedParticles GetExpectedAttributes ДобавитьСхему
Initialize Если вызывается метод Initialize по умолчанию, GetExpectedParticles возвращает массив, содержащий все глобальные элементы.

Если перегруженный метод Initialize, который принимает XmlSchemaObject в качестве параметра, вызывается для инициализации частичной проверки элемента, GetExpectedParticles возвращает только элемент, к которому был инициализирован объект XmlSchemaValidator.
Если вызывается метод Initialize по умолчанию, GetExpectedAttributes возвращает пустой массив.

Если перегрузка метода Initialize, принимающего XmlSchemaObject в качестве параметра, вызывается для инициализации частичной проверки атрибута, GetExpectedAttributes возвращает только атрибут, к которому был инициализирован объект XmlSchemaValidator.
Добавляет схему в XmlSchemaSet объекта XmlSchemaValidator, если она не имеет ошибок предварительной обработки.
ValidateElement Если элемент контекста действителен, GetExpectedParticles возвращает последовательность элементов, ожидаемых в качестве дочерних элементов контекстного элемента.

Если элемент контекста недопустим, GetExpectedParticles возвращает пустой массив.
Если элемент контекста действителен и если вызов ValidateAttribute ранее не был выполнен, GetExpectedAttributes возвращает список всех атрибутов, определенных в элементе контекста.

Если некоторые атрибуты уже проверены, GetExpectedAttributes возвращает список оставшихся атрибутов для проверки.

Если элемент контекста недопустим, GetExpectedAttributes возвращает пустой массив.
То же, что выше.
ValidateAttribute Если атрибут контекста является атрибутом верхнего уровня, GetExpectedParticles возвращает пустой массив.

В противном случае GetExpectedParticles возвращает последовательность элементов, ожидаемых в качестве первого дочернего элемента контекста.
Если атрибут контекста является атрибутом верхнего уровня, GetExpectedAttributes возвращает пустой массив.

В противном случае GetExpectedAttributes возвращает список оставшихся атрибутов для проверки.
То же, что выше.
GetUnspecifiedDefaultAttributes GetExpectedParticles возвращает последовательность элементов, ожидаемых в качестве первого дочернего элемента контекста. GetExpectedAttributes возвращает список обязательных и необязательных атрибутов, которые еще не проверены для элемента контекста. То же, что выше.
ValidateEndOfAttributes GetExpectedParticles возвращает последовательность элементов, ожидаемых в качестве первого дочернего элемента контекста. GetExpectedAttributes возвращает пустой массив. То же, что выше.
ValidateText Если contentType элемента контекста имеет значение Mixed, GetExpectedParticles возвращает последовательность элементов, ожидаемых в следующей позиции.

Если тип содержимого элемента контекста — TextOnly или Empty, GetExpectedParticles возвращает пустой массив.

Если элемент контекста contentType имеет значение ElementOnly, GetExpectedParticles возвращает последовательность элементов, ожидаемых в следующей позиции, но произошла ошибка проверки.
GetExpectedAttributes возвращает список атрибутов, не проверенных элементом контекста. То же, что выше.
ValidateWhitespace Если контекстный пробел является пробелом верхнего уровня, GetExpectedParticles возвращает пустой массив.

В противном случае поведение метода GetExpectedParticles совпадает с поведением ValidateText.
Если контекст пробелов является верхнеуровневым пробелом, GetExpectedAttributes возвращает пустой массив.

В противном случае поведение метода GetExpectedAttributes совпадает с поведением ValidateText.
То же, что выше.
ValidateEndElement GetExpectedParticles возвращает последовательность элементов, ожидаемых после элемента контекста (возможные братья и сестры). GetExpectedAttributes возвращает список атрибутов, не проверенных элементом контекста.

Если элемент контекста не имеет родительского элемента, GetExpectedAttributes возвращает пустой список (элемент контекста является родительским элементом текущего элемента, на котором был вызван ValidateEndElement).
То же, что выше.
SkipToEndElement Эквивалентно ValidateEndElement. Эквивалентно ValidateEndElement. То же, что выше.
EndValidation Возвращает пустой массив. Возвращает пустой массив. То же, что выше.

Примечание.

Значения, возвращаемые различными свойствами класса XmlSchemaValidator, не изменяются путем вызова любого из методов в приведенной выше таблице.

См. также