如果您愿意,可以在XML数据文件的顶部嵌入一个XML模式。这样就可以在单个XML文件中包含数据和验证需求以方便传输了。这叫做内嵌模式。当XML模式嵌入到同一个将要被验证的XML文档中时,如这里的内嵌模式,将会发生有趣的现象。在这种情况下,模式将作为源文档的要素部分出现。而且,它是文档根元素的直接子元素。
模式是一个XML子树,逻辑上与将要验证的文档处于同一个级别。可是一个格式良好的XML文档不会有两个根。因此一个包罗万象的根节点必须创建有两个子节点:模式和文档。您将在程序清单5-6中看到这样的示例,该示例在名为<root>的根节点上引入了一个新的XML元素。这段代码包含了XSD模式以及将要验证的XML数据作为它的子 节点。
程序清单5-6 包含内嵌XSD模式的XML文件
<?xml version="1.0"?>
<root xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:x="urn:authors">
<!-- Start of Schema -->
<xs:schema targetNamespace="urn:authors">
<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>
<!-- End of Schema -->
<x: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>
</x:authors>
</root>
请注意在程序清单5-6中,根元素不能成功地通过验证,因为没有关于它的模式信息。当ValidationType属性设置为ValidationType.Schema时,如果检测到内嵌模式,则XmlReader类将抛出对根元素的警告。在您建立验证代码的时候请记住这一点。如果嵌入了XSD代码,那么一个强大的错误过滤器将会保证一个完全合法的XML文档。程序清单5-7显示的代码验证了包含在XML文件中的内嵌XSD模式。
程序清单5-7 通过内嵌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_InlineSchema.xml";
XmlReader reader = null;
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += new
ValidationEventHandler(this.ValidationEventHandler);
settings.ValidationFlags &=
XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags &=
XmlSchemaValidationFlags.ReportValidationWarnings;
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)
{
if (args.Severity == XmlSeverityType.Error)
{
_builder.Append("Validation error: " + args.Message + "<br>");
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Inline XSD Schema Validation</title>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
取消ProcessInlineSchema和ReportValidationWarnings的代码是以上程序清单与之前程序清单之间的差别。为了指定由XmlReaderSettings类使用的模式选项,可以将XmlReaderSettings类的ValidationFlags属性赋给XmlSchemaValidationFlags枚举的一个值。以下代码实现了这个目的。
settings.ValidationFlags &= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags &= XmlSchemaValidationFlags.ReportValidationWarnings;
除了用于这个示例的值以外,XmlSchemaValidationFlags枚举还提供了表5-6中显示的值。
表5-6 XmlSchemaValidationFlags枚举值
值 |
说 明 |
AllowXmlAttribute |
允许xml属性,即使没有在模式中定义 |
None |
使用默认验证选项并且不执行模式验证选项 |
ProcessIdentityConstraints |
处理在验证中遇到的身份约束,如xs:ID、xs:IDREF、xs:key、xs:keyref、xs:unique |
(续表)
值 |
说 明 |
ProcessInlineSchema |
处理在验证中遇到的内嵌模式 |
ProcessSchemaLocation |
处理在验证中遇到的模式地址提示,如xsi:schameLocation、xsi:noNamespaceSchemaLocation |
ReportValidationWarnings |
报告在验证中遇到的模式验证警告 |
注意在ValidationEventHandler中使用XmlSeverityType枚举对由解析器生成的警告进行过滤。这些警告生成的原因是包含内嵌模式的根元素被认为不是验证的一部分。
if (args.Severity == XmlSeverityType.Error)
{
_builder.Append("Validation error: " + args.Message + "<br>");
}
对XmlSeverityType.Error的检查将保证在验证事件处理程序中只捕捉错误。
注意:
虽然XML模式作为一种格式而成为被广泛接受的规范,但是却不能同样地形容内嵌模式。一般的做法是尽可能地避免内嵌XML模式。这可以改善带宽管理(一次传输尽可能多的模式)并让您远离不良后果。通过XmlReaderSettings对象,您可以在模式缓存中重新加载模式并在分析源XML数据时使用这些模式。