默认情况下,该XmlDocument 类不会根据 XML 架构定义语言(XSD)架构或文档类型定义(DTD)验证文档对象模型(DOM)中的 XML;XML 仅验证格式正确。
若要验证 DOM 中的 XML,可以通过将架构验证XmlReader传递给类的方法,或使用类的方法Load验证 DOM 中以前未验证的 XmlDocument XML 文档,来验证 XML 加载到 Validate DOM XmlDocument 中。
在 XML 文档加载到 DOM 中时验证该文档
当验证传递到类的方法XmlDocument时XmlReader,该Load类会验证 XML 数据,因为它加载到 XmlDocument DOM 中。
成功验证后,将应用架构默认值、根据需要将文本值转换为原子值,类型信息与验证的信息项相关联。 因此,类型化的 XML 数据取代了以前非类型化的 XML 数据。
创建 XML Schema-Validating XmlReader
若要创建 XML 架构验证 XmlReader,请执行以下步骤。
构造一个新 XmlReaderSettings 实例。
将 XML 架构添加到 Schemas 实例的属性 XmlReaderSettings 。
指定
Schema
为 ValidationType.(可选)指定 ValidationFlags 并 ValidationEventHandler 处理验证期间遇到的架构验证错误和警告。
最后,将 XmlReaderSettings 对象与 XML 文档一起传递给 Create 类的方法 XmlReader ,从而创建架构验证 XmlReader。
示例:
在下面的代码示例中,架构验证 XmlReader 将验证加载到 DOM 中的 XML 数据。 对 XML 文档进行无效修改,然后重新验证文档,导致架构验证错误。 最后,更正了其中一个错误,然后部分验证 XML 文档。
using System;
using System.Xml;
using System.Xml.Schema;
class XmlDocumentValidationExample
{
static void Main(string[] args)
{
try
{
// Create a schema validating XmlReader.
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");
settings.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandler);
settings.ValidationFlags = settings.ValidationFlags | XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationType = ValidationType.Schema;
XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);
// The XmlDocument validates the XML document contained
// in the XmlReader as it is loaded into the DOM.
XmlDocument document = new XmlDocument();
document.Load(reader);
// Make an invalid change to the first and last
// price elements in the XML document, and write
// the XmlSchemaInfo values assigned to the price
// element during load validation to the console.
XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
manager.AddNamespace("bk", "http://www.contoso.com/books");
XmlNode priceNode = document.SelectSingleNode(@"/bk:bookstore/bk:book/bk:price", manager);
Console.WriteLine($"SchemaInfo.IsDefault: {priceNode.SchemaInfo.IsDefault}");
Console.WriteLine($"SchemaInfo.IsNil: {priceNode.SchemaInfo.IsNil}");
Console.WriteLine($"SchemaInfo.SchemaElement: {priceNode.SchemaInfo.SchemaElement}");
Console.WriteLine($"SchemaInfo.SchemaType: {priceNode.SchemaInfo.SchemaType}");
Console.WriteLine($"SchemaInfo.Validity: {priceNode.SchemaInfo.Validity}");
priceNode.InnerXml = "A";
XmlNodeList priceNodes = document.SelectNodes(@"/bk:bookstore/bk:book/bk:price", manager);
XmlNode lastprice = priceNodes[priceNodes.Count - 1];
lastprice.InnerXml = "B";
// Validate the XML document with the invalid changes.
// The invalid changes cause schema validation errors.
document.Validate(ValidationEventHandler);
// Correct the invalid change to the first price element.
priceNode.InnerXml = "8.99";
// Validate only the first book element. The last book
// element is invalid, but not included in validation.
XmlNode bookNode = document.SelectSingleNode(@"/bk:bookstore/bk:book", manager);
document.Validate(ValidationEventHandler, bookNode);
}
catch (XmlException ex)
{
Console.WriteLine($"XmlDocumentValidationExample.XmlException: {ex.Message}");
}
catch(XmlSchemaValidationException ex)
{
Console.WriteLine($"XmlDocumentValidationExample.XmlSchemaValidationException: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"XmlDocumentValidationExample.Exception: {ex.Message}");
}
}
static void ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.Write("\nWARNING: ");
else if (args.Severity == XmlSeverityType.Error)
Console.Write("\nERROR: ");
Console.WriteLine(args.Message);
}
}
Imports System.Xml
Imports System.Xml.Schema
Class XmlDocumentValidationExample
Shared Sub Main()
Try
' Create a schema validating XmlReader.
Dim settings As XmlReaderSettings = New XmlReaderSettings()
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")
AddHandler settings.ValidationEventHandler, New ValidationEventHandler(AddressOf ValidationEventHandler)
settings.ValidationFlags = settings.ValidationFlags And XmlSchemaValidationFlags.ReportValidationWarnings
settings.ValidationType = ValidationType.Schema
Dim reader As XmlReader = XmlReader.Create("contosoBooks.xml", settings)
' The XmlDocument validates the XML document contained
' in the XmlReader as it is loaded into the DOM.
Dim document As XmlDocument = New XmlDocument()
document.Load(reader)
' Make an invalid change to the first and last
' price elements in the XML document, and write
' the XmlSchemaInfo values assigned to the price
' element during load validation to the console.
Dim manager As XmlNamespaceManager = New XmlNamespaceManager(document.NameTable)
manager.AddNamespace("bk", "http://www.contoso.com/books")
Dim priceNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager)
Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault)
Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil)
Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement)
Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType)
Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity)
priceNode.InnerXml = "A"
Dim priceNodes As XmlNodeList = document.SelectNodes("/bk:bookstore/bk:book/bk:price", manager)
Dim lastprice As XmlNode = priceNodes(priceNodes.Count - 1)
lastprice.InnerXml = "B"
' Validate the XML document with the invalid changes.
' The invalid changes cause schema validation errors.
document.Validate(AddressOf ValidationEventHandler)
' Correct the invalid change to the first price element.
priceNode.InnerXml = "8.99"
' Validate only the first book element. The last book
' element is invalid, but not included in validation.
Dim bookNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book", manager)
document.Validate(AddressOf ValidationEventHandler, bookNode)
Catch ex As XmlException
Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message)
Catch ex As XmlSchemaValidationException
Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message)
Catch ex As Exception
Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message)
End Try
End Sub
Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)
If args.Severity = XmlSeverityType.Warning Then
Console.Write(vbCrLf & "WARNING: ")
Else
If args.Severity = XmlSeverityType.Error Then
Console.Write(vbCrLf & "ERROR: ")
End If
End If
Console.WriteLine(args.Message)
End Sub
End Class
该示例将 contosoBooks.xml
文件作为输入。
<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
<book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Benjamin</first-name>
<last-name>Franklin</last-name>
</author>
<price>8.99</price>
</book>
<book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
<title>The Confidence Man</title>
<author>
<first-name>Herman</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
</book>
<book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
<title>The Gorgias</title>
<author>
<name>Plato</name>
</author>
<price>9.99</price>
</book>
</bookstore>
该示例还采用 contosoBooks.xsd
该文件作为输入。
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.contoso.com/books" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="bookstore">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="book">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string" />
<xs:element name="author">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string" />
<xs:element minOccurs="0" name="first-name" type="xs:string" />
<xs:element minOccurs="0" name="last-name" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="price" type="xs:decimal" />
</xs:sequence>
<xs:attribute name="genre" type="xs:string" use="required" />
<xs:attribute name="publicationdate" type="xs:date" use="required" />
<xs:attribute name="ISBN" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
验证 XML 数据并将其加载到 DOM 时,请考虑以下事项。
在上面的示例中,每当遇到无效类型时, ValidationEventHandler 将调用该类型。 如果未对验证设置 aValidationEventHandler,则当调用任何属性或元素类型与验证架构中指定的相应类型不匹配时XmlReader,将引发 aXmlSchemaValidationException。Load
将 XML 文档加载到 XmlDocument 具有定义默认值的关联架构的对象中时, XmlDocument 这些默认值将视为在 XML 文档中出现。 这意味着该 IsEmptyElement 属性始终返回
false
架构中默认的元素。 即使在 XML 文档中,它也被编写为空元素。
在 DOM 中验证 XML 文档
类 Validate 的方法 XmlDocument 根据对象属性中的 XmlDocument 架构验证 DOM 中加载的 Schemas XML 数据。 成功验证后,将应用架构默认值、根据需要将文本值转换为原子值,类型信息与验证的信息项相关联。 因此,类型化的 XML 数据取代了以前非类型化的 XML 数据。
下面的示例类似于上面的“在 XML 文档加载到 DOM 时验证 XML 文档”中的示例。 在此示例中,XML 文档未在加载到 DOM 中时进行验证,而是在使用 Validate 类的方法 XmlDocument 加载到 DOM 后进行验证。 该方法
using System;
using System.Xml;
using System.Xml.Schema;
class XmlDocumentValidationExample
{
static void Main(string[] args)
{
try
{
// Create a new XmlDocument instance and load
// the XML document into the DOM.
XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
// Add the XML schema for the XML document to the
// Schemas property of the XmlDocument.
document.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");
// Validate the XML document loaded into the DOM.
document.Validate(ValidationEventHandler);
// Make an invalid change to the first and last
// price elements in the XML document, and write
// the XmlSchemaInfo values assigned to the price
// element during validation to the console.
XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
manager.AddNamespace("bk", "http://www.contoso.com/books");
XmlNode priceNode = document.SelectSingleNode(@"/bk:bookstore/bk:book/bk:price", manager);
Console.WriteLine($"SchemaInfo.IsDefault: {priceNode.SchemaInfo.IsDefault}");
Console.WriteLine($"SchemaInfo.IsNil: {priceNode.SchemaInfo.IsNil}");
Console.WriteLine($"SchemaInfo.SchemaElement: {priceNode.SchemaInfo.SchemaElement}");
Console.WriteLine($"SchemaInfo.SchemaType: {priceNode.SchemaInfo.SchemaType}");
Console.WriteLine($"SchemaInfo.Validity: {priceNode.SchemaInfo.Validity}");
priceNode.InnerXml = "A";
XmlNodeList priceNodes = document.SelectNodes(@"/bk:bookstore/bk:book/bk:price", manager);
XmlNode lastprice = priceNodes[priceNodes.Count - 1];
lastprice.InnerXml = "B";
// Validate the XML document with the invalid changes.
// The invalid changes cause schema validation errors.
document.Validate(ValidationEventHandler);
// Correct the invalid change to the first price element.
priceNode.InnerXml = "8.99";
// Validate only the first book element. The last book
// element is invalid, but not included in validation.
XmlNode bookNode = document.SelectSingleNode(@"/bk:bookstore/bk:book", manager);
document.Validate(ValidationEventHandler, bookNode);
}
catch (XmlException ex)
{
Console.WriteLine($"XmlDocumentValidationExample.XmlException: {ex.Message}");
}
catch(XmlSchemaValidationException ex)
{
Console.WriteLine($"XmlDocumentValidationExample.XmlSchemaValidationException: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"XmlDocumentValidationExample.Exception: {ex.Message}");
}
}
static void ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.Write("\nWARNING: ");
else if (args.Severity == XmlSeverityType.Error)
Console.Write("\nERROR: ");
Console.WriteLine(args.Message);
}
}
Imports System.Xml
Imports System.Xml.Schema
Class XmlDocumentValidationExample
Shared Sub Main()
Try
' Create a new XmlDocument instance and load
' the XML document into the DOM.
Dim document As XmlDocument = New XmlDocument()
document.Load("contosoBooks.xml")
' Add the XML schema for the XML document to the
' Schemas property of the XmlDocument.
document.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")
' Validate the XML document loaded into the DOM.
document.Validate(AddressOf ValidationEventHandler)
' Make an invalid change to the first and last
' price elements in the XML document, and write
' the XmlSchemaInfo values assigned to the price
' element during validation to the console.
Dim manager As XmlNamespaceManager = New XmlNamespaceManager(document.NameTable)
manager.AddNamespace("bk", "http://www.contoso.com/books")
Dim priceNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager)
Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault)
Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil)
Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement)
Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType)
Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity)
priceNode.InnerXml = "A"
Dim priceNodes As XmlNodeList = document.SelectNodes("/bk:bookstore/bk:book/bk:price", manager)
Dim lastprice As XmlNode = priceNodes(priceNodes.Count - 1)
lastprice.InnerXml = "B"
' Validate the XML document with the invalid changes.
' The invalid changes cause schema validation errors.
document.Validate(AddressOf ValidationEventHandler)
' Correct the invalid change to the first price element.
priceNode.InnerXml = "8.99"
' Validate only the first book element. The last book
' element is invalid, but not included in validation.
Dim bookNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book", manager)
document.Validate(AddressOf ValidationEventHandler, bookNode)
Catch ex As XmlException
Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message)
Catch ex As XmlSchemaValidationException
Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message)
Catch ex As Exception
Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message)
End Try
End Sub
Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)
If args.Severity = XmlSeverityType.Warning Then
Console.Write(vbCrLf & "WARNING: ")
Else
If args.Severity = XmlSeverityType.Error Then
Console.Write(vbCrLf & "ERROR: ")
End If
End If
Console.WriteLine(args.Message)
End Sub
End Class
该示例采用上述“验证 XML 文档时加载到 DOM”中引用的输入 contosoBooks.xml
和 contosoBooks.xsd
文件。
处理验证错误和警告
验证 DOM 中加载的 XML 数据时,将报告 XML 架构验证错误。 在加载 XML 数据时或在验证以前未验证的 XML 文档时,会收到有关所有架构验证错误的通知。
验证错误由 ValidationEventHandler. 如果为实例分配了某个ValidationEventHandler实例或传递给XmlReaderSettings类的方法Validate,XmlDocument则它将处理架构验证错误;否则在遇到架构验证错误时引发。ValidationEventHandlerXmlSchemaValidationException
注释
尽管架构验证错误导致 XML 数据加载到 DOM 中,除非引发 ValidationEventHandler 异常以停止进程。
除非向对象指定ReportValidationWarnings了标志,否则XmlReaderSettings不会报告架构验证警告。
有关说明 ValidationEventHandler示例,请参阅上面的“在将 XML 文档加载到 DOM 时验证 XML 文档”和“在 DOM 中验证 XML 文档”。