You can validate an XML document against a schema, by using built in XmlReader’s validation features. Note: You can find more details about XML schemas from the article How to use XML Schemas in XML document. You can follow the next steps when performing validation:
1. You need to import the System.Xml.Schema namespace, which contains types such as XmlSchema and XmlSchemaCollection:
Using System.Xml.Schema;
2. You need to create the validation reader, by using XmlReaderSettings object that specifically indicates that you want to perform validation. You can do this by setting the ValidationType property and loading your XSD schema file into the Schemas collection, as shown here:
// Configure the reader to use validation.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
// Create the path for the schema file.
string schemaFile = Path.Combine(Request.PhysicalApplicationPath, @”App_Data\BooksList.xsd”);
// Indicate that elements in the namespace
// https://www.Books.com/BooksList should be validated using the schema file.
settings.Schemas.Add(“https://www.Books.com/BooksList”,schemaFile);
3. You need to create the validation reader, by using the static XmlReader.Create() method. This method has several overloads, but you can use a FileStream (with the XML document) and the XmlReaderSettings object that has your validation settings:
// Open the XML file.
FileStream fs = new FileStream(file, FileMode.Open);
// Create the validating reader.
XmlReader r = XmlReader.Create(fs, settings);
The XmlReader in this example works in the same way as is explained in the articles How to use XmlTextReader to read XML file as text in C# or How to use XmlTextReader to read XML file as objects in C# , but it adds the ability to verify that the XML document follows the schema rules. This reader throws an exception (or raises an event) to indicate errors as you move through the XML file.
The following example shows how you can create a validating reader that uses the BooksList.xsd file to verify that the XML in BooksList.xml is valid:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Xml.Schema;
using System.IO;
namespace ValidateXMLVC
{
public partial class XMLValidator : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
XMLFileValidator();
}
}
protected void XMLFileValidator()
{
// Configure the reader to use validation.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
// Connect to the method named ValidateHandler.
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
// Create the path for the schema file.
string schemaFile = Path.Combine(Request.PhysicalApplicationPath, @”App_Data\BooksList.xsd”);
// Indicate that elements in the namespace
// https://www.Books.com/BooksList should be validated using the schema file.
settings.Schemas.Add(“urn:books”, schemaFile);
// Open a stream to the file.
string file = Path.Combine(Request.PhysicalApplicationPath, @”App_Data\BooksList.xml”);
FileStream fs = new FileStream(file, FileMode.Open);
// Create the validating reader.
XmlReader r = XmlReader.Create(fs, settings);
// Create a generic collection of books.
List<Book> books = new List<Book>();
// Loop through the books.
lblStatus.Text = “”;
while (r.Read())
{
if (r.NodeType == XmlNodeType.Element && r.Name == “Book”)
{
Book newBook = new Book();
// Get the rest of the subtags for this book
while (r.NodeType != XmlNodeType.EndElement)
{
r.Read();
// Look for ISBN
if (r.Name == “ISBN-13”)
{
while (r.NodeType != XmlNodeType.EndElement)
{
r.Read();
if (r.NodeType == XmlNodeType.Text)
{
newBook.Isbn13 = r.Value;
}
}
}
r.Read();
// Look for Title
if (r.Name == “Title”)
{
while (r.NodeType != XmlNodeType.EndElement)
{
r.Read();
if (r.NodeType == XmlNodeType.Text)
{
newBook.Title = r.Value;
}
}
}
r.Read();
// Look for Author subtags.
if (r.Name == “Author”)
{
while (r.NodeType != XmlNodeType.EndElement)
{
r.Read();
if (r.NodeType == XmlNodeType.Text)
{
newBook.Author = r.Value;
}
}
}
r.Read();
if (r.Name == “Price”)
{
while (r.NodeType != XmlNodeType.EndElement)
{
r.Read();
if (r.NodeType == XmlNodeType.Text)
{
newBook.Price = Decimal.Parse(r.Value);
}
}
}
r.Read();
if (r.Name == “Available”)
{
while (r.NodeType != XmlNodeType.EndElement)
{
r.Read();
if (r.NodeType == XmlNodeType.Text)
{
newBook.Available = Boolean.Parse(r.Value);
}
}
}
}
books.Add(newBook);
}
} // end of while
fs.Close();
if (!(lblStatus.Text.Length > 0))
{
gridResult.DataSource = books;
gridResult.DataBind();
}
}
}
}
Using the current file, this code will succeed, and you’ll be able to access each node in the document. However, consider what happens if you make the minor modification shown here:
<Author>J.K. Rowling</Author>
<Price>1x.99</Price>
Now when you try to validate the document, an XmlSchemaException (from the System.Xml.Schema namespace) will be thrown, alerting you to the invalid data type, as shown in:
Instead of catching errors, you can react to the XmlReaderSettings.ValidationEventHandler event. If you react to this event, you’ll be provided with information about the error, but no exception will be thrown. To connect an event handler to this event, you can attach an event handler before you create the XmlReader:
// Connect to the method named ValidateHandler.
settings.ValidationEventHandler += new ValidationEventHandler(ValidateHandler);
The event handler receives a ValidationEventArgs object as a parameter, which contains the exception, a message, and a number representing the severity:
public void ValidateHandler(Object sender, ValidationEventArgs e)
{
lblStatus.Text += “Error: ” + e.Message + “<br>”;
}
The next picture shows the result of failed validation attempt: