在驗證某個xml文檔是否符合某個格式時,你還在使用用代碼一個節點一個節點、一個屬性一個屬性讀取、判斷的方法嗎?呵呵,那可就落後了,.Net Framework提供了一些好用的基礎設施來協助我們來完成這項工作。
我們先把這些基礎設施給列一下(其介紹是從MSDN中Copy下來的,我就懶得翻譯啦):
1. XmlReader
provides forward-only, read-only access to a stream of XML data. The XmlReader class conforms to the W3C Extensible Markup Language (XML) 1.0 and the Namespaces in XML recommendations.
Although the Microsoft .NET Framework includes concrete implementations of the XmlReader class, such as the XmlTextReader, XmlNodeReader, and the XmlValidatingReader classes, in the 2.0 release the recommended practice is to create XmlReader instances using the Create method. For more information, see Creating XML Readers.
2. XmlReaderSettings
Specifies a set of features to support on the XmlReader object created by the Create method.
使用XmlReaderSettings需要注意的地方:
1) The ProcessInlineSchema and ProcessSchemaLocation validation flags of an XmlReaderSettings object are not set by default. When these flags are set, the XmlResolver of the XmlReaderSettings object is used to resolve schema locations encountered in the instance document in the XmlReader. If the XmlResolver object is a null reference (Nothing in Visual Basic), schema locations are not resolved even if the ProcessInlineSchema and ProcessSchemaLocation validation flags are set.
2) Schemas added during validation add new types and can change the validation outcome of the document being validated. As a result, external schemas should only be resolved from trusted sources.
3) Validation error messages may expose sensitive content model information. Validation error and warning messages are handled using the ValidationEventHandler delegate, or are exposed as an XmlSchemaValidationException if no event handler is provided to the XmlReaderSettings object (validation warnings do not cause an XmlSchemaValidationException to be thrown). This content model information should not be exposed in untrusted scenarios. Validation warning messages are suppressed by default and can be reported by setting the ReportValidationWarnings flag.
4) The SourceUri property of an XmlSchemaValidationException returns the URI path to the schema file that caused the exception. The SourceUri property should not be exposed in untrusted scenarios.
5) Disabling the ProcessIdentityConstraints flag (enabled by default) is recommended when validating, untrusted, large XML documents in high availability scenarios against a schema with identity constraints over a large part of the document.
6) XmlReaderSettings objects can contain sensitive information such as user credentials. You should be careful when caching XmlReaderSettings objects, or when passing the XmlReaderSettings object from one component to another.
7) DTD processing is disabled by default. If you enable DTD processing, you need to be aware of including DTDs from untrusted sources and possible denial of service attacks. Use the XmlSecureResolver to restrict the resources that the XmlReader can access.
8) Do not accept supporting components, such as NameTable, XmlNamespaceManager, and XmlResolver objects, from an untrusted source.
基礎設施列完了,那我們應該如何開始這驗證的旅程呢?
首先,建立一XmlReaderSettings對象,在XmlReaderSettings對象中設定好相應的屬性,我們希望使用Schema來驗證讀入的xml檔案, 把對象的ValidationType屬性設定成類型,指定驗證事件處理器,並把Schema的檔案名稱和其命名空間加入到Schema集合中:
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add("urn:example-schema", "example.xsd");
settings.ValidationEventHandler += new ValidationEventHandler(checkCallback);
然後,把這個XmlReaderSettings對象作為XmlReader類的Create方法的參數,獲得得一個XmlReader對象
XmlReader reader = XmlReader.Create("example_data.xml", settings);
這樣,這個XmlReader對象在執行Read方法時,會使用我們指定的Schema檔案驗證其讀取的xml檔案:
while (reader.Read())
{
…
}
我們把所有的的代碼合在一塊:
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add("urn:example-schema", "example.xsd");
settings.ValidationEventHandler += new ValidationEventHandler(checkCallback);
XmlReader reader = XmlReader.Create("example_data.xml", settings);
try
{
while (reader.Read())
{
…
}
}
finally
{
reader.Close();
}
看看,是不是比以前一個節點一個節點、一個屬性一個屬性讀取、判斷的方法要簡潔多了?