11.4 验证XML

上面几节阐述了如何读写或者操作XML文档,但这些XML文档都没有经过正确的验证。如果试图尝试访问一个无效的XML文档内容,那么就会得到一个错误。因此,需要在操作XML文档之前来验证XML文档的正确性。

11.4.1 XML架构

XML架构是用于定义和验证XML数据的内容和结构的文档,就像数据库架构定义和验证组成数据库的表、列和数据类型一样。XML架构通过XML架构定义语言((XL Schema Definition, XSD)定义和描述某些XML数据类型。XML架构元素(元素、属性、类型和组)用于定义某些XML数据类型的有效结构、有效数据内容和关系。当然,XML架构还可为属性和元素提供默认值。

在实际开发中,可以使用XML架构来保证应用程序和单位之间共享的某些XML数据类型的一致性。XML架构可用做两个应用程序之间进行数据交换的合同。单位可以发布描述其应用程序生成和使用的XML格式的架构。这样,希望交换数据的其他单位和应用程序可以围绕这些架构生成它们的应用程序,以便它们的XML消息能被理解。例如,在买方和卖方之间发送以XML表示的订单之前,可以用XML架构对其进行验证。该验证校验数据的所有元素均存在,都按预期顺序排列,并且均为正确的数据类型。这确保订单收件人在收到它时能够正确解释数据。

架构定义如下面的示例MyBook.xsd所示。


<?xml version="1.0"encoding="utf-8"?>

<xs:schema id="MyBook"

targetNamespace="http://tempuri.org/MyBook.xsd"

elementFormDefault="qualified"

xmlns="http://tempuri.org/MyBook.xsd"

xmlns:mstns="http://tempuri.org/MyBook.xsd"

xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="MyBook">

<xs:complexType>

<xs:sequence>

<xs:element maxOccurs="unbounded"name="book">

<xs:complexType>

<xs:sequence>

<xs:element name="description"type="xs:string"/>

<xs:element name="price"type="xs:double"/>

<xs:element name="press"type="xs:string"/>

<xs:element name="author"type="xs:string"/>

</xs:sequence>

<xs:attribute name="id"type="xs:decimal"/>

<xs:attribute name="name"type="xs:string"/>

</xs:complexType>

</xs:element>

</xs:sequence>

</xs:complexType>

</xs:element>

</xs:schema>


详细的定义知识请参考MSDN,鉴于篇幅与本书重点的原因,这里就不再继续做详细阐述。

11.4.2 验证XmlDocument

创建好MyBook.xsd之后,就可以利用它验证MyBook.xml文档的正确性。其中,验证XML文档的一般步骤如下:

1)创建一个XmlReaderSettings对象的实例。XmlReaderSettings类允许指定一套由XmlReader对象支持的选项,并且这些选项将会在解析XML数据的时候起作用。如下面的代码所示:


XmlReaderSettings settings=new XmlReaderSettings();


2)将XmlReaderSettings的ValidationType属性设置为ValidationType.Schema。如下面的代码所示:


settings.ValidationType=ValidationType.Schema;


3)通过XmlReaderSettings类的Schema属性将XSD模式添加至XmlReaderSettings类。如下面的代码所示:


settings.Schemas.Add(null, Server.MapPath("MyBook.xsd"));


需要注意的是,这里的Add方法第一个参数是targetNamespace的值,如果为null,则表示采用XSD文件里targetNamespace属性的值。如果要传递此参数,务必与targetNamespace的值一致。

4)定义一个ValidationEventHandler事件处理程序方法。如下面的代码所示:


void settings_ValidationEventHandler(object sender,

System.Xml.Schema.ValidationEventArgs e)

{

Response.Write(e.Message+"<br/>");

}


ValidationEventHandler事件定义了一个事件处理程序,用于接收关于XSD模式验证错误的通知。验证的错误和警告通过ValidationEventHandler回调函数来报告。验证错误不会停止解析,解析只会在XML文档不是格式良好时停止。但是,如果没有提供验证事件处理程序的回调函数并且发生了验证错误,将会抛出异常。使用验证事件回调机制捕获所有验证错误的这种方式可以在单步过程中发现所有的验证错误。

5)将前面定义好的ValidationEventHandler事件处理程序方法与XmlReaderSettings类相关联。如下面的代码所示:


settings.ValidationEventHandler+=new

System.Xml.Schema.ValidationEventHandler(

settings_ValidationEventHandler);


6)在解析XML数据时,XmlReader类使用Read方法验证XML文档。如下面的代码所示:


XmlReader reader=XmlReader.Create(Server.MapPath("MyBook.xml"),

settings);

while(reader.Read())

{

}

reader.Close();


完整的验证示例如下面的代码所示:


protected void Page_Load(object sender, EventArgs e)

{

XmlReaderSettings settings=new XmlReaderSettings();

//验证类型设置为模式((xd)

settings.ValidationType=ValidationType.Schema;

//为XmlReaderSettings对象添加模式

settings.Schemas.Add(null, Server.MapPath("MyBook.xsd"));

//添加验证错误的处理事件

settings.ValidationEventHandler+=new

System.Xml.Schema.ValidationEventHandler(settings_ValidationEventHandler);

//同理第一个参数必须是绝对路径或物理路径

XmlReader reader=

XmlReader.Create(Server.MapPath("MyBook.xml"),settings);

while(reader.Read())

{}

reader.Close();

Response.Write("验证完毕");

}

void settings_ValidationEventHandler(object sender,

System.Xml.Schema.ValidationEventArgs e)

{

Response.Write(e.Message+"<br/>");

}


上面的代码使用了MyBook.xsd对MyBook.xml进行了验证,如果MyBook.xml符合验证规则,则验证通过,否则输出验证的错误信息。例如把MyBook.xml文档改写成下面的形式,再运行程序进行验证。


<?xml version="1.0"?>

<!——创建时间@2010-6-10 17:45:41——>

<?xml-stylesheet type="text/xsl"href="MyBook.xsl"?>

<MyBook xmlns="http://www.comesns.com/aspnet/">

<!——易学C#——>

<book id="1"name="易学C#">

<description>一本C#学习书籍</description>

<price>45元</price>

<press>人民邮电出版社</press>

<author>马伟</author>

</book>

<!——ASP.NET4程序设计——>

<book id="2"name="ASP.NET4程序设计">

<description>一本ASP.NET学习书籍</description>

<price>100元</price>

<press>机械工业出版社</press>

<author>马伟</author>

</book>

</MyBook>


因为price在MyBook.xsd中定义为double类型,而上面的MyBook.xml却将它定义成了string类型,所以会输出验证错误信息。运行结果如图11-11所示。

figure_0421_0314

图 11-11 示例运行结果

在对XML进行验证中,XmlReaderSettings类提供了验证XML数据的核心基础。它的常用属性如下所示:

❑DtdProcessing:获取或设置Dtd Processing枚举。DtdProcessing枚举指定用于处理DTD的选项。

❑Schemas:获取或设置在执行架构验证时使用的XmlSchemaSet对象,该对象表示用于执行模式验证的模式集合。

❑ValidationType:获取或设置一个值,该值指示XmlReader在读取时是否执行验证或类型分配。允许的选择验证类型值为None、Auto、DTD、XDR和Schema。

❑ValidationFlags:获取或设置一个指示架构验证设置的值。此设置应用于验证架构的XmlReader对象((VlidationType属性设置为ValidationType.Schema)。

为了能够使用XmlReaderSettings类来验证XML数据,必须将XmlReaderSettings类的属性设置为正确的值。还需要说明的是,这个类本身无法运行,它需要与XmlReader或者XmlNodeReader实例一同运行。