使用 XPathNavigator 验证架构

更新:November 2007

使用 XmlDocument 类,可以通过两种方式验证 XmlDocument 对象中包含的 XML 内容。 第一种方式是使用验证 XmlReader 对象验证 XML 内容,第二种方式是使用 XmlDocument 类的 Validate 方法。 还可以使用 XPathDocument 类对 XML 内容执行只读验证。

验证 XML 数据

默认情况下,XmlDocument 类不使用 DTD 或 XML 架构定义语言 (XSD) 架构验证来验证 XML 文档。 只验证 XML 文档的格式是否正确。

第一种验证 XML 文档的方式是使用验证 XmlReader 对象,在文档加载到 XmlDocument 对象时进行验证。 第二种方式是使用 XmlDocument 类的 Validate 方法验证以前非类型化的 XML 文档。 在这两种情况下,均可以使用 XmlDocument 类的 Validate 方法重新验证对经过验证的 XML 文档的更改。

在文档加载时进行验证

验证 XmlReader 对象通过将 XmlReaderSettings 对象传递给 XmlReader 类的 Create 方法进行创建,该方法使用 XmlReaderSettings 对象作为参数。 作为参数传递的 XmlReaderSettings 对象将 ValidationType 属性设置为 Schema,并将 XmlDocument 对象中包含的 XML 文档的 XML 架构添加到其 Schemas 属性中。 然后,使用验证 XmlReader 对象创建 XmlDocument 对象。

以下示例在 contosoBooks.xml 文件加载到 XmlDocument 对象时进行验证,方法是使用验证 XmlReader 对象创建 XmlDocument 对象。 因为 XML 文档符合其架构,所以,未生成任何架构验证错误或警告。

Imports System
Imports System.Xml
Imports System.Xml.Schema
Imports System.Xml.XPath
 
Class ValidatingReaderExample

    Shared Sub Main(ByVal args() As String)

        Try
            Dim settings As XmlReaderSettings = New XmlReaderSettings()
            settings.Schemas.Add("https://www.contoso.com/books", "contosoBooks.xsd")
            settings.ValidationType = ValidationType.Schema

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

            Dim document As XmlDocument = New XmlDocument()
            document.Load(reader)
            Dim navigator As XPathNavigator = document.CreateNavigator()

        Catch e As Exception
            Console.WriteLine("ValidatingReaderExample.Exception: {0}", e.Message)
        End Try

    End Sub

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

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

    End Sub

End Class
using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;

class ValidatingReaderExample
{
    static void Main(string[] args)
    {
        try
        {
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.Schemas.Add("https://www.contoso.com/books", "contosoBooks.xsd");
            settings.ValidationType = ValidationType.Schema;

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

            XmlDocument document = new XmlDocument();
            document.Load(reader);
            XPathNavigator navigator = document.CreateNavigator();
        }
        catch (Exception e)
        {
            Console.WriteLine("ValidatingReaderExample.Exception: {0}", e.Message);
        }
    }

    static void SchemaValidationHandler(object sender, ValidationEventArgs e)
    {
        switch (e.Severity)
        {
            case XmlSeverityType.Error:
                Console.WriteLine("Schema Validation Error: {0}", e.Message);
                break;
            case XmlSeverityType.Warning:
                Console.WriteLine("Schema Validation Warning: {0}", e.Message);
                break;
        }
    }
}

该示例使用 contosoBooks.xml 文件作为输入。

<bookstore xmlns="https://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="https://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>

在上面的示例中,如果任何属性或元素类型不匹配验证架构中指定的相应类型,则调用 Load 时将引发 XmlSchemaValidationException。 如果在验证 XmlReader 时设置 ValidationEventHandler,则遇到无效类型时将调用 ValidationEventHandler

XPathNavigator 访问 TypedValue 设置为 invalid 的属性或元素时,将引发 XmlSchemaException

Validity 属性可用于确定用 XPathNavigator 访问属性或元素时单个属性或元素是否有效。

说明:

如果 XML 文档加载到 XmlDocument 对象,并且具有关联的架构来定义默认值,XmlDocument 对象对待这些默认值就像出现在 XML 文档中一样。 这意味着对于架构中的默认元素,IsEmptyElement 属性始终返回 false,即使在 XML 文档中,也将编写为空元素。

使用验证方法验证文档

XmlDocument 类的 Validate 方法针对 XmlDocument 对象的 Schemas 属性中指定的架构验证 XmlDocument 对象中包含的 XML 文档,然后执行信息集增加。 结果是 XmlDocument 中以前非类型化的 XML 文档由类型化的文档取代。

XmlDocument 对象使用作为参数传递给 Validate 方法的 ValidationEventHandler 委托报告架构验证错误和警告。

以下示例针对 XmlDocument 对象的 Schemas 属性中包含的 contosoBooks.xsd 架构验证 XmlDocument 对象中包含的 contosoBooks.xml 文件。

Imports System
Imports System.Xml
Imports System.Xml.Schema
Imports System.Xml.XPath
 
Class ValidateExample

    Shared Sub Main(ByVal args() As String)

        Dim document As XmlDocument = New XmlDocument()
        document.Load("contosoBooks.xml")
        Dim navigator As XPathNavigator = document.CreateNavigator()

        document.Schemas.Add("https://www.contoso.com/books", "contosoBooks.xsd")
        Dim validation As ValidationEventHandler = New ValidationEventHandler(AddressOf SchemaValidationHandler)

        document.Validate(validation)

    End Sub

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

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

    End Sub

End Class
using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;

class ValidateExample
{
    static void Main(string[] args)
    {
        XmlDocument document = new XmlDocument();
        document.Load("contosoBooks.xml");
        XPathNavigator navigator = document.CreateNavigator();

        document.Schemas.Add("https://www.contoso.com/books", "contosoBooks.xsd");
        ValidationEventHandler validation = new ValidationEventHandler(SchemaValidationHandler);

        document.Validate(validation);
    }

    static void SchemaValidationHandler(object sender, ValidationEventArgs e)
    {
        switch (e.Severity)
        {
            case XmlSeverityType.Error:
                Console.WriteLine("Schema Validation Error: {0}", e.Message);
                break;
            case XmlSeverityType.Warning:
                Console.WriteLine("Schema Validation Warning: {0}", e.Message);
                break;
        }
    }
}

该示例使用 contosoBooks.xml 文件作为输入。

<bookstore xmlns="https://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="https://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 文档进行修改之后,可以使用 XmlDocument 类的 Validate 方法针对 XML 文档的架构验证修改。

以下示例在 contosoBooks.xml 文件加载到 XmlDocument 对象时进行验证,方法是使用验证 XmlReader 对象创建 XmlDocument 对象。 XML 文档在加载时成功进行验证,未生成任何架构验证错误或警告。 然后,示例对 XML 文档进行了两处符合 contosoBooks.xsd 架构的修改。 第一处修改是插入一个无效的子元素,从而引发架构验证错误,第二处修改是将类型化节点的值设置为不符合节点类型的值,从而引发异常。

Imports System
Imports System.Xml
Imports System.Xml.Schema
Imports System.Xml.XPath
 
Class ValidatingReaderExample

    Shared Sub Main(ByVal args() As String)

        Try
            Dim settings As XmlReaderSettings = New XmlReaderSettings()
            settings.Schemas.Add("https://www.contoso.com/books", "contosoBooks.xsd")
            settings.ValidationType = ValidationType.Schema

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

            Dim document As XmlDocument = New XmlDocument()
            document.Load(reader)
            Dim navigator As XPathNavigator = document.CreateNavigator()

            Dim validation As ValidationEventHandler = New ValidationEventHandler(AddressOf SchemaValidationHandler)

            navigator.MoveToChild("bookstore", "https://www.contoso.com/books")
            navigator.MoveToChild("book", "https://www.contoso.com/books")
            navigator.MoveToChild("author", "https://www.contoso.com/books")

            navigator.AppendChild("<title>Book Title</title>")

            document.Validate(validation)

            navigator.MoveToParent()
            navigator.MoveToChild("price", "https://www.contoso.com/books")
            navigator.SetTypedValue(DateTime.Now)
        Catch e As Exception
            Console.WriteLine("ValidatingReaderExample.Exception: {0}", e.Message)
        End Try

    End Sub

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

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

    End Sub

End Class
using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;

class ValidatingReaderExample
{
    static void Main(string[] args)
    {
        try
        {
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.Schemas.Add("https://www.contoso.com/books", "contosoBooks.xsd");
            settings.ValidationType = ValidationType.Schema;

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

            XmlDocument document = new XmlDocument();
            document.Load(reader);
            XPathNavigator navigator = document.CreateNavigator();

            ValidationEventHandler validation = new ValidationEventHandler(SchemaValidationHandler);

            navigator.MoveToChild("bookstore", "https://www.contoso.com/books");
            navigator.MoveToChild("book", "https://www.contoso.com/books");
            navigator.MoveToChild("author", "https://www.contoso.com/books");

            navigator.AppendChild("<title>Book Title</title>");
            
            document.Validate(validation);

            navigator.MoveToParent();
            navigator.MoveToChild("price", "https://www.contoso.com/books");
            navigator.SetTypedValue(DateTime.Now);
        }
        catch (Exception e)
        {
            Console.WriteLine("ValidatingReaderExample.Exception: {0}", e.Message);
        }
    }

    static void SchemaValidationHandler(object sender, ValidationEventArgs e)
    {
        switch (e.Severity)
        {
            case XmlSeverityType.Error:
                Console.WriteLine("Schema Validation Error: {0}", e.Message);
                break;
            case XmlSeverityType.Warning:
                Console.WriteLine("Schema Validation Warning: {0}", e.Message);
                break;
        }
    }
}

该示例使用 contosoBooks.xml 文件作为输入。

<bookstore xmlns="https://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="https://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>

在上面的示例中,对 XmlDocument 对象中包含的 XML 文档进行了两处修改。 在 XML 文档加载时,遇到的任何架构验证错误将通过验证事件处理程序方法进行处理并写入控制台。

在此示例中,加载 XML 文档之后引入验证错误,并使用 XmlDocument 类的 Validate 方法发现错误。

使用 XPathNavigator 类的 SetTypedValue 方法进行的修改引发了 InvalidCastException,因为新值不符合节点的架构类型。

有关使用 SetTypedValue 方法修改值的更多信息,请参见使用 XPathNavigator 修改 XML 数据主题。

只读验证

XPathDocument 类是 XML 文档在内存中的只读表示形式。 XPathDocument 类和 XmlDocument 类均创建 XPathNavigator 对象来浏览和编辑 XML 文档。 因为 XPathDocument 类是只读类,从 XPathDocument 对象返回的 XPathNavigator 对象不能编辑 XPathDocument 对象中包含的 XML 文档。

在验证时,可以创建一个 XPathDocument 对象,就好像使用验证 XmlReader 对象创建 XmlDocument 对象一样,如本主题前面所述。 XPathDocument 对象在 XML 文档加载时进行验证,但是因为不能编辑 XPathDocument 对象中的 XML 数据,所以,无法重新验证 XML 文档。

有关只读的和可编辑的 XPathNavigator 对象的更多信息,请参见使用 XPathDocument 和 XmlDocument 读取 XML 数据主题。

请参见

概念

使用 XPath 数据模型处理 XML 数据

使用 XPathDocument 和 XmlDocument 读取 XML 数据

使用 XPathNavigator 选择、计算和匹配 XML 数据

使用 XPathNavigator 访问 XML 数据

使用 XPathNavigator 编辑 XML 数据

参考

XmlDocument

XPathDocument

XPathNavigator