XML文档包括了元素、属性和基本数据类型的值。在全章中,将使用一个名为Authors.xml的XML文档,该文档显示于程序清单5-1。
程序清单5-1 Authors.xml文件
<?xml version="1.0"?>
<authors>
<author>
<au_id>172-32-1176</au_id>
<au_lname>White</au_lname>
<au_fname>Johnson</au_fname>
<phone>408 496-7223</phone>
<address>10932 Bigge Rd.</address>
<city>Menlo Park</city>
<state>CA</state>
<zip>94025</zip>
<contract>true</contract>
</author>
<author>
<au_id>213-46-8915</au_id>
<au_lname>Green</au_lname>
<au_fname>Marjorie</au_fname>
<phone>415 986-7020</phone>
<address>309 63rd St. #411</address>
<city>Oakland</city>
<state>CA</state>
<zip>94618</zip>
<contract>true</contract>
</author>
</authors>
XSD模式定义了元素、属性以及它们之间的关系。它符合W3C的XML模式标准和建议标准。Authors.xml文档的XSD模式是Authors.xsd,显示在程序清单5-2中。
程序清单5-2 Authors.xsd文件
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault
="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="authors">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="author">
<xs:complexType>
<xs:sequence>
<xs:element name="au_id" type="xs:string" />
<xs:element name="au_lname" type="xs:string" />
<xs:element name="au_fname" type="xs:string" />
<xs:element name="phone" type="xs:string" />
<xs:element name="address" type="xs:string" />
<xs:element name="city" type="xs:string" />
<xs:element name="state" type="xs:string" />
<xs:element name="zip" type="xs:unsignedInt" />
<xs:element name="contract" type="xs:boolean" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
.NET Framework 2.0类支持W3C XML模式建议标准。一般部署的用来验证XML文档的类有XmlReader、XmlReaderSettings、XmlSchemaSet和XmlNodeReader。使用XSD模式进行XML文档验证的步骤顺序如下。
1. 验证XML文档的步骤
(1) 定义一个ValidationEventHandler事件处理程序方法。
(2) 创建XmlReaderSettings对象的实例。XmlReaderSettings类允许指定一套由XmlReader对象支持的选项,并且这些选项将会在解析XML数据的时候起作用。请注意XmlReaderSettings生成废弃的XmlValidatingReader类(用于.NET 1.x版本)。
(3) 将前面定义好的ValidationEventHandler方法与XmlReaderSettings类相关联。
(4) 将XmlReaderSettings的ValidationType属性设置为ValidationType.Schema。
(5) 通过XmlReaderSettings类的Schema属性将XSD模式添加至XmlReaderSettings类。
(6) 在解析XML数据的时候,XmlReader类使用Read方法验证XML文档。
验证事件处理程序
ValidationEventHandler事件定义了一个事件处理程序,用于接收关于XSD模式验证错误的通知。验证的错误和警告通过ValidationEventHandler回调函数来报告。验证错误不会停止解析,解析只会在XML文档不是格式良好时停止。但是,如果您没有提供验证事件处理程序的回调函数并且发生了验证错误,将会抛出异常。使用验证事件回调机制捕获所有验证错误的这种方式可以在单步过程中发现所有的验证错误。
XML验证中XmlReaderSettings类的角色
XmlReaderSettings类和XmlReader类一样是最重要的类之一,它提供了验证XML数据的核心基础。表5-1提供了XmlReaderSettings类中验证相关属性的简要描述,本章后部分将会利用这些属性。
表5-1 验证X mlReaderSettings类的相关属性和事件
属 性 |
说 明 |
ProhibitDtd |
指示XmlReaderSettings类是否支持DTD验证。默认值是true,表示不支持DTD验证 |
ValidationType |
指定XmlReaderSettings类支持的验证类型。允许的验证类型是DTD、XSD和None |
ValidationEventHandler |
指定事件处理程序,用于接收关于验证事件的信息 |
ValidationFlags |
指定在验证XML数据时将被强制执行的附加的验证设置,如使用内嵌模式、身份约束和XML属性 |
Schemas |
获得或者设置XmlSchemaSet对象,该对象表示用于执行模式验证的模式集合 |
为了能够使用XmlReaderSettings类来验证XML数据,必须将XmlReaderSettings类的属性设置为正确的值。这个类本身无法运行,而需要与XmlReader或者XmlNodeReader实例一同运行。您可以使用这个类并依据DTD或XML模式进行验证。
2. 一个XML验证的示例
既然您对XML数据的验证步骤有了一个大概的了解,那么现在就来看一个示例并理解它是如何实际工作的。程序清单5-3利用Authors.xsd模式文件来验证Authors.xml文件。
程序清单5-3 使用XSD模式验证XML数据
<%@ Page Language="C#"%>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Xml.Schema" %>
<script runat="server">
private StringBuilder _builder = new StringBuilder();
void Page_Load(object sender, EventArgs e)
{
string xmlPath = Request.PhysicalApplicationPath +
@""App_Data"Authors.xml";
string xsdPath = Request.PhysicalApplicationPath +
@""App_Data"Authors.xsd";
XmlReader reader = null;
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationEventHandler += new
ValidationEventHandler(this.ValidationEventHandler);
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(null, XmlReader.Create(xsdPath));
reader = XmlReader.Create(xmlPath, settings);
while (reader.Read())
{
}
if (_builder.ToString() == String.Empty)
Response.Write("Validation completed successfully.");
else
Response.Write("Validation Failed. <br>" + _builder.ToString());
}
void ValidationEventHandler(object sender, ValidationEventArgs args)
{
_builder.Append("Validation error: " + args.Message + "<br>");
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>XSD Validation</title>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
在研究以上代码之前,图5-1显示了由程序清单5-3生成的输出。
图 5-1
在代码开始处,程序清单5-3声明了用于保存XML和XSD模式文件路径的变量。然后创建了XmlReaderSettings对象的实例并将其与验证事件处理程序的回调方法相关联。
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationEventHandler += new
ValidationEventHandler(this.ValidationEventHandler);
然后,它将XmlReaderSettings类的ValidationType属性设置为ValidationType.Schema,通知XmlReader对象在解析XML数据的时候使用所提供的XSD模式进行XML数据验证。
settings.ValidationType = ValidationType.Schema;
除了模式之外,ValidationType枚举还支持其他值,这些值列在表5-2中。
表5-2 ValidationiType枚举值
值 |
说 明 |
DTD |
指示将使用DTD执行验证 |
None |
不执行验证,也不抛出验证错误 |
Schema |
根据XML模式(包括内嵌的XSD模式)验证XML文档 |
随后代码将Authors.xsd文件添加至XmlReaderSettings对象的模式集合。此后,它会调用XmlReader对象的静态Create方法并传入Authors.xml文件的路径和XmlReaderSettings对象。Create方法返回XmlReader对象的实例,该实例就会在分析文档的时候使用DTD或XML模式执行验证。
settings.Schemas.Add(null, XmlReader.Create(xsdPath));
reader = XmlReader.Create(xmlPath, settings);
因为XmlReader对象是通过在Create方法中传入XmlReaderSettings对象而创建的,所以XmlReaderSettings中的设置将被XmlReader对象支持。然后在While循环中调用XmlReader对象的Read方法来读取并验证整个XML文件。只要发生验证错误就会调用ValidationEventHandler方法。在这个方法中,StringBuilder对象一直将验证错误消息内容添加至本身。如果没有提供验证事件处理程序,那么当出现验证错误的时候就会抛出XmlSchemaException异常。
3. 处理XML验证中的异常
在程序清单5-3中,只要出现了XML验证错误,控制就会自动转向ValidationEventHandler方法,来处理异常并将验证错误消息(通过ValidationEventArgs对象的Message属性获得)添加至StringBuilder对象。如果StringBuilder对象包含了所有消息,最后这个错误消息将会显示给用户。虽然这对本示例来说已经足够,但是很多时候您会想要区分不同的异常类型,如在验证过程中产生的警告或者错误。为了达到这个目的,可以检查ValidationEventArgs对象的Severity属性。这个属性返回XmlSeverityType类的枚举,可用于判断产生的异常类型。表5-3显示了这个枚举所包含的值。
表5-3 XmlSeverityType枚举值
值 |
描 述 |
Error |
指示在验证实例文档时出现了验证错误。这可以是使用DTD和XSD模式的验证结果。如果没有验证事件处理程序来处理这种情况,将会抛出异常 |
Warning |
指示验证解析器已经运行到一个没有错误但是有必要警告用户的情况之下。Warning和Error的不同之处是它不会在调用方法的应用程序中抛出异常 |
例如,如果只想过滤在验证过程中产生的错误,则可以通过使用如下代码来达到这个目的。
private void ValidationEventHandler(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Error)
{
//Add code to handle the errors
}
}