- XML Reader Navigation
- Reading Attributes
- Movement and Advanced Reads
- Creation Using XMLWriter
- Validating Your Work
- Summary
Validating Your Work
The ValidatingReader class is the gateway to XML schema validation in the .NET framework. It takes XmlTextReader as a parameter and layers validation functionality on top of it. The first requirement is having an XML schema document that describes the form of allowable XML content. Listing 11 shows the schema document that describes the purchase order that you have worked with in the article series. The other requirement is to have a document to parse. Listing 12 is POError.xml, which has a HomeAddress element instead of a BillToAddress element, to allow you to build a program that responds to validation errors.
Listing 11: PO.xsd Schema Document
<?xml version="1.0" encoding="utf-8" ?> <xsd:schema id="PO" targetNamespace="http://michalk.com/XmlDOM/PO.xsd" xmlns="http://michalk.com/XmlDOM/PO.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="PurchaseOrder"> <xsd:complexType> <xsd:sequence> <xsd:element name="Number" type="xsd:string" /> <xsd:element name="OrderDate" type="xsd:string" /> <xsd:element name="BillToAddress" type="AddressType" /> <xsd:element name="ShipToAddress" type="AddressType" /> <xsd:element name="LineItem" type="LineItemType" minOccurs="1" maxOccurs="unbounded" /> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:complexType name="AddressType"> <xsd:sequence> <xsd:element name="Street" type="xsd:string" /> <xsd:element name="City" type="xsd:string" /> <xsd:element name="State" type="xsd:string" /> <xsd:element name="ZipCode" type="xsd:string" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="LineItemType"> <xsd:sequence></xsd:sequence> <xsd:attribute name="SKU" type="xsd:string" /> <xsd:attribute name="Price" type="xsd:decimal" /> <xsd:attribute name="Qty" type="xsd:integer" /> <xsd:attribute name="Description" type="xsd:string" /> <xsd:attribute name="Name" type="xsd:string" /> </xsd:complexType> </xsd:schema>
Listing 12: POError.xml Purchase Order with Error
<?xml version="1.0" encoding="utf-8" ?> <po:PurchaseOrder xmlns:po="http://michalk.com/XmlDOM/PO.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Number>1001</Number> <OrderDate>8/12/01</OrderDate> <HomeAddress> <Street>101 Main Street</Street> <City>Charlotte</City> <State>NC</State> <ZipCode>28273</ZipCode> </HomeAddress> <ShipToAddress> <Street>101 Main Street</Street> <City>Charlotte</City> <State>NC</State> <ZipCode>28273</ZipCode> </ShipToAddress> <LineItem Name="Computer Desk" Description="Wood desk for computer" SKU="12345A123" Price="499.99" Qty="1" /> </po:PurchaseOrder>
Listing 13 shows how to set up the XmlValidatingReader. The first step is to create an XmlTextReader that opens up POError.xml and then pass that into the XmlValidatingReader's constructor. You can specify XSD validation using the ValidationType property. The next step is to add the schema document to the schema cache of the reader. Using the schema cache can provide a performance boost if you are validating against multiple documents. It is an optional step if the document has an internal link that the XmlValidatingReader can use to find the schema document.
To handle the errors, you can link up to the ValidationEventHandler event to the static OnValidationEvent method. When the validator reaches a piece of invalid XML content, it calls the specified method. The node display information is turned off in this example so that you can see the error messages on the console. Listing 14 is the final result. Notice how it detects the HomeAddress problem and balks on each of its subordinate elements.
Listing 13: Purchase Order with Error Validation Code
using System; using System.Xml; using System.Xml.Schema; namespace XmlDemos { public class ReaderNavValidate { public static void Main() { // load the PO document that has errors XmlTextReader textreader = new XmlTextReader("POError.xml"); // ignore the whitespace in the document textreader.WhitespaceHandling = WhitespaceHandling.None; // create the Validating reader XmlValidatingReader reader = new XmlValidatingReader(textreader); // validate using the XSD XML schema spec reader.ValidationType = ValidationType.Schema; // load the schema document into a schema cache // (this helps performance when doing multiple validations) XmlSchemaCollection xsc = new XmlSchemaCollection(); xsc.Add("http://michalk.com/XmlDOM/PO.xsd", "PO.xsd"); // add schema cache to reader reader.Schemas.Add(xsc); // link up into the validation event mechanism // to have it call our OnValidationEvent method reader.ValidationEventHandler += new ValidationEventHandler(ReaderNavValidate.OnValidationEvent); Console.WriteLine("Walking nodes in document..\n"); // read each node in the document // using the default traversal path while (reader.Read()) { } } public static void OnValidationEvent(Object o, ValidationEventArgs e) { Console.WriteLine("Validation Error: {0}",e.Message); } } }
Listing 14: Purchase Order with Error Output
Walking nodes in document.. Validation Error: Element 'http://michalk.com/XmlDOM /PO.xsd:PurchaseOrder' has invalid content. Expected 'BillToAddress'. An error occurred at file:///C:/Documents and Settings/dalemi/My Documents/Visual Studio Projects/Xml/bin/Debug/POError.xml(5, 3). Validation Error: Could not find schema information for the element 'HomeAddress'. An error occurred at file:///C:/Documents and Settings /dalemi/My Documents/Visual Studio Projects/XmlDemos/bin/Debug/ POError.xml(5, 3). Validation Error: Could not find schema information for the element 'Street'. An error occurred at file:///C:/Documents and Settings/dalemi /My Documents/VisualStudio Projects/XmlDemos/bin/Debug /POError.xml(6, 4). Validation Error: Could not find schema information for the element 'City'. An error occurred at file:///C:/Documents and Settings/dalemi /My Documents/Visual Studio Projects/XmlDemos/bin/Debug /POError.xml(7, 4). Validation Error: Could not find schema information for the element 'State'. An error occurred at file:///C:/Documents and Settings/dalemi /My Documents/Visual Studio Projects/XmlDemos/bin/Debug /POError.xml(8, 4). Validation Error: Could not find schema information for the element 'ZipCode'. An error occurred at file:///C:/Documents and Settings/dalemi /My Documents/Visual Studio Projects/XmlDemos/bin/Debug
/POError.xml(9, 4).