如果您願意,可以在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資料時使用這些模式。